Skip to content

Commit

Permalink
Fix async hydration problems
Browse files Browse the repository at this point in the history
  • Loading branch information
daniil4 committed Oct 31, 2022
1 parent cd34b26 commit 1a89939
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 21 deletions.
24 changes: 6 additions & 18 deletions packages/wrapper/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -162,25 +162,13 @@ export const createWrapper = <S extends Store>(makeStore: MakeStore<S>, config:
};

const useHybridHydrate = (store: S, state: any) => {
const firstRender = useRef<boolean>(true);
const lastState = useRef<any>();

useEffect(() => {
firstRender.current = false;
}, []);

useMemo(() => {
// synchronous for server or first time render
if (getIsServer() || firstRender.current) {
hydrate(store, state);
}
}, [store, state]);

useEffect(() => {
// asynchronous for client subsequent navigation
if (!getIsServer()) {
hydrate(store, state);
}
}, [store, state]);
// synchronous for server and client render
if (lastState.current !== state) {
lastState.current = state;
hydrate(store, state);
}
};

const useWrappedStore = ({initialState, initialProps, ...props}: any, displayName = 'useWrappedStore'): {store: S; props: any} => {
Expand Down
30 changes: 27 additions & 3 deletions packages/wrapper/tests/client.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
**/

import * as React from 'react';
import {useDispatch} from 'react-redux';
import {create, act} from 'react-test-renderer';
import {DummyComponent, wrapper, child, makeStore} from './testlib';
import {useDispatch, useSelector} from 'react-redux';
import {create, act, ReactTestRenderer} from 'react-test-renderer';
import {DummyComponent, wrapper, child, makeStore, State} from './testlib';
import {createWrapper} from '../src';
import {Store} from 'redux';

Expand Down Expand Up @@ -63,4 +63,28 @@ describe('client integration', () => {
// expected when invoked above
await w.withRedux(Page)?.getInitialProps({} as any);
});

test('client side action override state from server', () => {
const stateFromClient = 'state from client';
const w = createWrapper(makeStore);

const Page: React.ComponentType<any> = () => {
const dispatch = useDispatch();
const reduxStatus = useSelector<State, string | undefined>(state => state.reduxStatus);
React.useEffect(() => {
// modifies the state,
dispatch({type: 'FOO', payload: stateFromClient});
}, [dispatch]);

return <>{reduxStatus}</>;
};

const Wrapped: any = w.withRedux(Page);

let renderer: ReactTestRenderer;
act(() => {
renderer = create(<Wrapped initialState={{reduxStatus: 'state from server'}} />);
});
expect(renderer!.toJSON()).toEqual(stateFromClient);
});
});

0 comments on commit 1a89939

Please sign in to comment.