@@ -2,12 +2,11 @@ import hoistStatics from 'hoist-non-react-statics'
2
2
import invariant from 'invariant'
3
3
import React , { Component , PureComponent } from 'react'
4
4
import propTypes from 'prop-types'
5
- import shallowEqual from 'shallow-equals'
6
5
import { isValidElementType } from 'react-is'
7
6
8
7
import Context from './Context'
9
8
10
- const Consumer = Context . Consumer
9
+ const ReduxConsumer = Context . Consumer
11
10
12
11
export default function connectAdvanced (
13
12
/*
@@ -52,14 +51,14 @@ export default function connectAdvanced(
52
51
withRef = false ,
53
52
54
53
// the context consumer to use
55
- consumer = Consumer ,
54
+ consumer = ReduxConsumer ,
56
55
57
56
// additional options are passed through to the selectorFactory
58
57
...connectOptions
59
58
} = { }
60
59
) {
61
- invariant ( ! withRef ,
62
- `withRef is removed. To access the wrapped instance, simply pass in ref `
60
+ invariant ( renderCountProp === undefined ,
61
+ `renderCountProp is removed. render counting is built into the latest React dev tools profiling extension `
63
62
)
64
63
65
64
invariant ( storeKey === 'store' ,
@@ -69,26 +68,39 @@ export default function connectAdvanced(
69
68
'ConnectedComponent consumer={context.Consumer} /></Provider>'
70
69
)
71
70
71
+ const Consumer = consumer
72
+
72
73
return function wrapWithConnect ( WrappedComponent ) {
73
74
invariant (
74
75
isValidElementType ( WrappedComponent ) ,
75
76
`You must pass a component to the function returned by ` +
76
77
`${ methodName } . Instead received ${ JSON . stringify ( WrappedComponent ) } `
77
78
)
79
+ invariant ( ! withRef || withRef === 'forwardRef' ,
80
+ 'withRef must be set to the text "forwardRef." Reference uses React.forwardRef and you may now access ref ' +
81
+ `directly instead of using getWrappedInstance() in component ${ wrappedComponentName } `
82
+ )
78
83
79
84
const wrappedComponentName = WrappedComponent . displayName
80
85
|| WrappedComponent . name
81
86
|| 'Component'
82
87
83
88
const displayName = getDisplayName ( wrappedComponentName )
84
89
85
- class PureWrapper extends PureComponent {
90
+ class PureWrapper extends Component {
91
+ shouldComponentUpdate ( nextProps ) {
92
+ return nextProps . derivedProps !== this . props . derivedProps
93
+ }
94
+
86
95
render ( ) {
87
- const { forwardRef, ... props } = this . props
88
- return < WrappedComponent { ...props } ref = { forwardRef } />
96
+ let { forwardRef, derivedProps } = this . props
97
+ return < WrappedComponent { ...derivedProps } ref = { forwardRef } />
89
98
}
90
99
}
100
+
91
101
PureWrapper . propTypes = {
102
+ count : propTypes . object ,
103
+ derivedProps : propTypes . object ,
92
104
forwardRef : propTypes . oneOfType ( [
93
105
propTypes . func ,
94
106
propTypes . object
@@ -108,19 +120,31 @@ export default function connectAdvanced(
108
120
WrappedComponent
109
121
}
110
122
111
- class Connect extends Component {
123
+ const OuterBase = connectOptions . pure ? PureComponent : Component
124
+
125
+ class Connect extends OuterBase {
112
126
constructor ( props ) {
113
127
super ( props )
114
- invariant ( ! props [ storeKey ] ,
115
- 'Passing redux store in props has been removed and does not do anything. ' +
116
- 'To use a custom redux store for a single component, ' +
117
- 'create a custom React context with React.createContext() and pass the Provider to react-redux\'s provider ' +
118
- 'and the Consumer to this component as in <Provider context={context.Provider}><' +
119
- wrappedComponentName + ' consumer={context.Consumer} /></Provider>'
120
- )
128
+ if ( withRef ) {
129
+ invariant ( ! props . props [ storeKey ] ,
130
+ 'Passing redux store in props has been removed and does not do anything. ' +
131
+ 'To use a custom redux store for a single component, ' +
132
+ 'create a custom React context with React.createContext() and pass the Provider to react-redux\'s provider ' +
133
+ 'and the Consumer to this component as in <Provider context={context.Provider}><' +
134
+ wrappedComponentName + ' consumer={context.Consumer} /></Provider>'
135
+ )
136
+ } else {
137
+ invariant ( ! props [ storeKey ] ,
138
+ 'Passing redux store in props has been removed and does not do anything. ' +
139
+ 'To use a custom redux store for a single component, ' +
140
+ 'create a custom React context with React.createContext() and pass the Provider to react-redux\'s provider ' +
141
+ 'and the Consumer to this component as in <Provider context={context.Provider}><' +
142
+ wrappedComponentName + ' consumer={context.Consumer} /></Provider>'
143
+ )
144
+
145
+ }
121
146
this . memoizeDerivedProps = this . makeMemoizer ( )
122
147
this . renderWrappedComponent = this . renderWrappedComponent . bind ( this )
123
- this . renderCount = 0
124
148
}
125
149
126
150
makeMemoizer ( ) {
@@ -132,7 +156,7 @@ export default function connectAdvanced(
132
156
let called = false
133
157
return ( state , props , store ) => {
134
158
if ( called ) {
135
- const sameProps = connectOptions . pure && shallowEqual ( lastProps , props )
159
+ const sameProps = connectOptions . pure && lastProps === props
136
160
const sameState = lastState === state
137
161
if ( sameProps && sameState ) {
138
162
return lastDerivedProps
@@ -146,7 +170,7 @@ export default function connectAdvanced(
146
170
lastProps = props
147
171
lastState = state
148
172
const nextProps = sourceSelector ( state , props )
149
- if ( shallowEqual ( lastDerivedProps , nextProps ) ) {
173
+ if ( lastDerivedProps === nextProps ) {
150
174
return lastDerivedProps
151
175
}
152
176
lastDerivedProps = nextProps
@@ -156,46 +180,56 @@ export default function connectAdvanced(
156
180
157
181
renderWrappedComponent ( value ) {
158
182
invariant ( value ,
159
- `Could not find "store" in either the context of ` +
183
+ `Could not find "store" in the context of ` +
160
184
`"${ displayName } ". Either wrap the root component in a <Provider>, ` +
161
185
`or pass a custom React context provider to <Provider> and the corresponding ` +
162
- `React context consumer to ${ displayName } .`
186
+ `React context consumer to ${ displayName } in connect options .`
163
187
)
164
188
const { state, store } = value
165
- const { forwardRef, ...otherProps } = this . props
166
- let derivedProps = this . memoizeDerivedProps ( state , otherProps , store )
189
+ if ( withRef ) {
190
+ const { forwardRef, props } = this . props
191
+ let derivedProps = this . memoizeDerivedProps ( state , props , store )
192
+ if ( connectOptions . pure ) {
193
+ return < PureWrapper derivedProps = { derivedProps } forwardRef = { forwardRef } />
194
+ }
167
195
168
- if ( renderCountProp ) {
169
- derivedProps = { ...derivedProps , [ renderCountProp ] : this . renderCount ++ }
196
+ return < WrappedComponent { ...derivedProps } ref = { forwardRef } />
170
197
}
198
+ let derivedProps = this . memoizeDerivedProps ( state , this . props , store )
171
199
if ( connectOptions . pure ) {
172
- return < PureWrapper { ... derivedProps } forwardRef = { forwardRef } />
200
+ return < PureWrapper derivedProps = { derivedProps } />
173
201
}
174
- return < WrappedComponent { ...derivedProps } ref = { forwardRef } />
202
+
203
+ return < WrappedComponent { ...derivedProps } />
175
204
}
176
205
177
206
render ( ) {
178
- const MyConsumer = this . props . consumer || consumer
179
207
return (
180
- < MyConsumer >
208
+ < Consumer >
181
209
{ this . renderWrappedComponent }
182
- </ MyConsumer >
210
+ </ Consumer >
183
211
)
184
212
}
185
213
}
186
214
187
215
Connect . WrappedComponent = WrappedComponent
188
216
Connect . displayName = displayName
189
- Connect . propTypes = {
190
- consumer : propTypes . object ,
191
- forwardRef : propTypes . oneOfType ( [
192
- propTypes . func ,
193
- propTypes . object
194
- ] )
217
+ if ( withRef ) {
218
+ Connect . propTypes = {
219
+ props : propTypes . object ,
220
+ forwardRef : propTypes . oneOfType ( [
221
+ propTypes . func ,
222
+ propTypes . object
223
+ ] )
224
+ }
225
+ }
226
+
227
+ if ( ! withRef ) {
228
+ return hoistStatics ( Connect , WrappedComponent )
195
229
}
196
230
197
231
function forwardRef ( props , ref ) {
198
- return < Connect { ... props } forwardRef = { ref } />
232
+ return < Connect props = { props } forwardRef = { ref } />
199
233
}
200
234
201
235
const forwarded = React . forwardRef ( forwardRef )
0 commit comments