Skip to content

Commit 0374936

Browse files
committed
Clean up and finish reworking Connect and Provider
1 parent 31fc951 commit 0374936

File tree

2 files changed

+29
-121
lines changed

2 files changed

+29
-121
lines changed

src/components/Provider.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export function createProvider(storeKey = 'store') {
7777
if (state.store !== props.store) {
7878
warnAboutReceivingStore()
7979
}
80+
return null;
8081
}
8182
}
8283

src/components/connectAdvanced.js

Lines changed: 28 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,11 @@
11
import hoistStatics from 'hoist-non-react-statics'
22
import invariant from 'invariant'
3-
import React, { Component, createElement } from 'react'
3+
import React, { Component, PureComponent, createElement } from 'react'
44

55
import {ReactReduxContext} from "./context";
6-
import shallowEqual from '../utils/shallowEqual'
76

87
let hotReloadingVersion = 0
9-
const dummyState = {}
10-
function noop() {}
11-
function makeSelectorStateful(sourceSelector) {
12-
// wrap the selector in an object that tracks its results between runs.
13-
const selector = {
14-
run: function runComponentSelector(props, storeState) {
15-
try {
16-
const nextProps = sourceSelector(storeState, props)
17-
if (nextProps !== selector.props || selector.error) {
18-
selector.shouldComponentUpdate = true
19-
selector.props = nextProps
20-
selector.error = null
21-
}
22-
} catch (error) {
23-
selector.shouldComponentUpdate = true
24-
selector.error = error
25-
}
26-
}
27-
}
288

29-
return selector
30-
}
319

3210
export default function connectAdvanced(
3311
/*
@@ -105,12 +83,13 @@ export default function connectAdvanced(
10583
}
10684

10785

86+
const OuterBaseComponent = connectOptions.pure ? PureComponent : Component;
87+
10888
class ConnectInner extends Component {
10989
constructor(props) {
11090
super(props);
11191

11292
this.state = {
113-
storeState : props.storeState,
11493
wrapperProps : props.wrapperProps,
11594
renderCount : 0,
11695
store : props.store,
@@ -131,7 +110,7 @@ export default function connectAdvanced(
131110

132111
static getChildPropsState(props, state) {
133112
try {
134-
const nextProps = state.childPropsSelector(state.storeState, props.wrapperProps)
113+
const nextProps = state.childPropsSelector(props.storeState, props.wrapperProps)
135114
if (nextProps === state.childProps) return null
136115
return { childProps: nextProps }
137116
} catch (error) {
@@ -140,20 +119,28 @@ export default function connectAdvanced(
140119
}
141120

142121
static getDerivedStateFromProps(props, state) {
143-
if ((connectOptions.pure && shallowEqual(props.wrapperProps, state.wrapperProps)) || state.error){
122+
const nextChildProps = ConnectInner.getChildPropsState(props, state)
123+
124+
if(nextChildProps === null) {
144125
return null;
145126
}
146127

147-
const nextChildProps = ConnectInner.getChildPropsState(props, state)
148-
149128
return {
150129
...nextChildProps,
151130
wrapperProps : props.wrapperProps,
152131
}
153132
}
154133

155134
shouldComponentUpdate(nextProps, nextState) {
156-
return nextState.childProps !== this.state.childProps;
135+
const childPropsChanged = nextState.childProps !== this.state.childProps;
136+
const storeStateChanged = nextProps.storeState !== this.props.storeState;
137+
const hasError = !!nextState.error;
138+
139+
let wrapperPropsChanged = false;
140+
141+
const shouldUpdate = childPropsChanged || hasError;
142+
return shouldUpdate;
143+
157144
}
158145

159146
render() {
@@ -165,75 +152,13 @@ export default function connectAdvanced(
165152
}
166153
}
167154

168-
class Connect extends Component {
155+
class Connect extends OuterBaseComponent {
169156
constructor(props) {
170157
super(props)
171158

172-
this.version = version
173-
this.renderCount = 0
174-
this.storeState = null;
175-
176-
177-
//this.setWrappedInstance = this.setWrappedInstance.bind(this)
178159
this.renderInner = this.renderInner.bind(this);
179-
180-
// TODO How do we express the invariant of needing a Provider when it's used in render()?
181-
/*
182-
invariant(this.store,
183-
`Could not find "${storeKey}" in either the context or props of ` +
184-
`"${displayName}". Either wrap the root component in a <Provider>, ` +
185-
`or explicitly pass "${storeKey}" as a prop to "${displayName}".`
186-
)
187-
*/
188160
}
189-
190-
componentDidMount() {
191-
if (!shouldHandleStateChanges) return
192-
193-
// componentWillMount fires during server side rendering, but componentDidMount and
194-
// componentWillUnmount do not. Because of this, trySubscribe happens during ...didMount.
195-
// Otherwise, unsubscription would never take place during SSR, causing a memory leak.
196-
// To handle the case where a child component may have triggered a state change by
197-
// dispatching an action in its componentWillMount, we have to re-run the select and maybe
198-
// re-render.
199-
this.selector.run(this.props, this.storeState);
200-
if (this.selector.shouldComponentUpdate) this.forceUpdate()
201-
}
202-
203-
204-
UNSAFE_componentWillReceiveProps(nextProps) {
205-
// TODO Do we still want/need to implement sCU / cWRP now?
206-
this.selector.run(nextProps, this.storeState);
207-
}
208-
209-
shouldComponentUpdate() {
210-
return this.selector.shouldComponentUpdate
211-
}
212-
213-
214-
componentWillUnmount() {
215-
this.selector.run = noop
216-
this.selector.shouldComponentUpdate = false
217-
}
218-
219-
getWrappedInstance() {
220-
invariant(withRef,
221-
`To access the wrapped instance, you need to specify ` +
222-
`{ withRef: true } in the options argument of the ${methodName}() call.`
223-
)
224-
return this.wrappedInstance
225-
}
226-
227-
setWrappedInstance(ref) {
228-
this.wrappedInstance = ref
229-
}
230-
231-
initSelector(dispatch, storeState) {
232-
const sourceSelector = selectorFactory(dispatch, selectorFactoryOptions)
233-
this.selector = makeSelectorStateful(sourceSelector)
234-
this.selector.run(this.props, storeState);
235-
}
236-
161+
/*
237162
addExtraProps(props) {
238163
if (!withRef && !renderCountProp) return props;
239164
@@ -247,37 +172,19 @@ export default function connectAdvanced(
247172
248173
return withExtras
249174
}
175+
*/
250176

251177
renderInner(providerValue) {
252178
const {storeState, store} = providerValue;
253179

254-
/*
255-
this.storeState = storeState;
256-
257-
if(this.selector) {
258-
this.selector.run(this.props, storeState);
259-
}
260-
else {
261-
this.initSelector(dispatch, storeState);
262-
}
263-
264-
if (this.selector.error) {
265-
// TODO This will unmount the whole tree now that we're throwing in render. Good idea?
266-
// TODO Related: https://github.com/reactjs/react-redux/issues/802
267-
throw this.selector.error
268-
}
269-
else if(this.selector.shouldComponentUpdate) {
270-
//console.log(`Re-rendering component (${displayName})`, this.selector.props);
271-
this.selector.shouldComponentUpdate = false;
272-
this.renderedElement = createElement(WrappedComponent, this.addExtraProps(this.selector.props));
273-
}
274-
else {
275-
//console.log(`Returning existing render result (${displayName})`, this.props)
276-
}
277-
278-
return this.renderedElement;
279-
*/
280-
return <ConnectInner storeState={storeState} store={store} wrapperProps={this.props} />
180+
return (
181+
<ConnectInner
182+
key={this.version}
183+
storeState={storeState}
184+
store={store}
185+
wrapperProps={this.props}
186+
/>
187+
);
281188
}
282189

283190
render() {
@@ -291,8 +198,8 @@ export default function connectAdvanced(
291198

292199
Connect.WrappedComponent = WrappedComponent
293200
Connect.displayName = displayName
201+
294202
// TODO We're losing the ability to add a store as a prop. Not sure there's anything we can do about that.
295-
//Connect.propTypes = contextTypes
296203

297204
// TODO With connect no longer managing subscriptions, I _think_ is is all unneeded
298205
/*

0 commit comments

Comments
 (0)