Skip to content

Commit 30178b7

Browse files
committed
Fix case where wrapper props changed before store update render
1 parent d210de1 commit 30178b7

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

src/components/connectAdvanced.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,10 @@ export default function connectAdvanced(
209209
const childPropsFromStoreUpdate = useRef()
210210

211211
const actualChildProps = usePureOnlyMemo(() => {
212-
if (childPropsFromStoreUpdate.current) {
212+
if (
213+
childPropsFromStoreUpdate.current &&
214+
wrapperProps === lastWrapperProps.current
215+
) {
213216
return childPropsFromStoreUpdate.current
214217
}
215218

test/components/hooks.spec.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ describe('React', () => {
3434
const mapStateSpy1 = jest.fn()
3535
const renderSpy1 = jest.fn()
3636

37+
let component1StateList
38+
3739
const component1Decorator = connect(state => {
3840
mapStateSpy1()
3941

@@ -42,9 +44,11 @@ describe('React', () => {
4244
}
4345
})
4446

45-
const component2 = props => {
47+
const component1 = props => {
4648
const [state, setState] = React.useState({ list: props.list })
4749

50+
component1StateList = state.list
51+
4852
React.useEffect(() => {
4953
setState(prevState => ({ ...prevState, list: props.list }))
5054
}, [props.list])
@@ -54,7 +58,7 @@ describe('React', () => {
5458
return <Component2 list={state.list} />
5559
}
5660

57-
const Component1 = component1Decorator(component2)
61+
const Component1 = component1Decorator(component1)
5862

5963
const mapStateSpy2 = jest.fn()
6064
const renderSpy2 = jest.fn()
@@ -67,33 +71,52 @@ describe('React', () => {
6771
}
6872
})
6973

70-
const component3 = () => {
74+
const component2 = props => {
7175
renderSpy2()
7276

77+
expect(props.list).toBe(component1StateList)
78+
7379
return <div>Hello</div>
7480
}
7581

76-
const Component2 = component2Decorator(component3)
82+
const Component2 = component2Decorator(component2)
7783

7884
rtl.render(
7985
<ProviderMock store={store}>
8086
<Component1 />
8187
</ProviderMock>
8288
)
8389

90+
// 1. Initial render
8491
expect(mapStateSpy1).toHaveBeenCalledTimes(1)
92+
93+
// 1.Initial render
94+
// 2. C1 useEffect
8595
expect(renderSpy1).toHaveBeenCalledTimes(2)
96+
97+
// 1. Initial render
8698
expect(mapStateSpy2).toHaveBeenCalledTimes(1)
99+
100+
// 1. Initial render
87101
expect(renderSpy2).toHaveBeenCalledTimes(1)
88102

89103
rtl.act(() => {
90104
store.dispatch({ type: 'FOO' })
91105
})
92106

107+
// 2. Store dispatch
93108
expect(mapStateSpy1).toHaveBeenCalledTimes(2)
109+
110+
// 3. Store dispatch
111+
// 4. C1 useEffect
94112
expect(renderSpy1).toHaveBeenCalledTimes(4)
113+
114+
// 2. Connect(C2) subscriber
115+
// 3. Ignored prev child props in re-render and re-runs mapState
95116
expect(mapStateSpy2).toHaveBeenCalledTimes(3)
96-
expect(renderSpy2).toHaveBeenCalledTimes(3)
117+
118+
// 2. Batched update from nested subscriber / C1 re-render
119+
expect(renderSpy2).toHaveBeenCalledTimes(2)
97120
})
98121
})
99122
})

0 commit comments

Comments
 (0)