Skip to content

Commit

Permalink
Merge 5ac79cb into cd34b26
Browse files Browse the repository at this point in the history
  • Loading branch information
kirill-konshin authored Dec 15, 2022
2 parents cd34b26 + 5ac79cb commit 3822c94
Show file tree
Hide file tree
Showing 31 changed files with 1,021 additions and 386 deletions.
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
115 changes: 53 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ import {AppProps} from 'next/app';
import {wrapper} from '../components/store';

const MyApp: FC<AppProps> = ({Component, ...rest}) => {
const {store, props} = wrapper.useWrappedStore(rest);
return (
<Provider store={store}>
<Component {...props.pageProps} />
</Provider>
);
const {store, props} = wrapper.useWrappedStore(rest);
return (
<Provider store={store}>
<Component {...props.pageProps} />
</Provider>
);
};
```

Expand Down Expand Up @@ -183,20 +183,20 @@ import {HYDRATE} from 'next-redux-wrapper';

// create your reducer
const reducer = (state = {tick: 'init'}, action) => {
switch (action.type) {
case HYDRATE:
const stateDiff = diff(state, action.payload) as any;
const wasBumpedOnClient = stateDiff?.page?.[0]?.endsWith('X'); // or any other criteria
return {
...state,
...action.payload,
page: wasBumpedOnClient ? state.page : action.payload.page, // keep existing state or use hydrated
};
case 'TICK':
return {...state, tick: action.payload};
default:
return state;
}
switch (action.type) {
case HYDRATE:
const stateDiff = diff(state, action.payload) as any;
const wasBumpedOnClient = stateDiff?.page?.[0]?.endsWith('X'); // or any other criteria
return {
...state,
...action.payload,
page: wasBumpedOnClient ? state.page : action.payload.page, // keep existing state or use hydrated
};
case 'TICK':
return {...state, tick: action.payload};
default:
return state;
}
};
```

Expand Down Expand Up @@ -431,35 +431,30 @@ import {State} from '../components/reducer';

// Since you'll be passing more stuff to Page
declare module 'next/dist/next-server/lib/utils' {
export interface NextPageContext {
store: Store<State>;
}
export interface NextPageContext {
store: Store<State>;
}
}

class MyApp extends App<AppInitialProps> {
public static getInitialProps = wrapper.getInitialAppProps(store => async context => {
store.dispatch({type: 'TOE', payload: 'was set in _app'});

public static getInitialProps = wrapper.getInitialAppProps(store => async context => {

store.dispatch({type: 'TOE', payload: 'was set in _app'});

return {
pageProps: {
// https://nextjs.org/docs/advanced-features/custom-app#caveats
...(await App.getInitialProps(context)).pageProps,
// Some custom thing for all pages
pathname: ctx.pathname,
},
};

});
return {
pageProps: {
// https://nextjs.org/docs/advanced-features/custom-app#caveats
...(await App.getInitialProps(context)).pageProps,
// Some custom thing for all pages
pathname: ctx.pathname,
},
};
});

public render() {
const {Component, pageProps} = this.props;
public render() {
const {Component, pageProps} = this.props;

return (
<Component {...pageProps} />
);
}
return <Component {...pageProps} />;
}
}

export default wrapper.withRedux(MyApp);
Expand All @@ -476,28 +471,24 @@ import App from 'next/app';
import {wrapper} from '../components/store';

class MyApp extends App {
static getInitialProps = wrapper.getInitialAppProps(store => async context => {

store.dispatch({type: 'TOE', payload: 'was set in _app'});

return {
pageProps: {
// https://nextjs.org/docs/advanced-features/custom-app#caveats
...(await App.getInitialProps(context)).pageProps,
// Some custom thing for all pages
pathname: ctx.pathname,
},
};
static getInitialProps = wrapper.getInitialAppProps(store => async context => {
store.dispatch({type: 'TOE', payload: 'was set in _app'});

});
return {
pageProps: {
// https://nextjs.org/docs/advanced-features/custom-app#caveats
...(await App.getInitialProps(context)).pageProps,
// Some custom thing for all pages
pathname: ctx.pathname,
},
};
});

render() {
const {Component, pageProps} = this.props;
render() {
const {Component, pageProps} = this.props;

return (
<Component {...pageProps} />
);
}
return <Component {...pageProps} />;
}
}

export default wrapper.withRedux(MyApp);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"lint:staged": "lint-staged --debug"
},
"devDependencies": {
"eslint": "8.6.0",
"eslint-config-ringcentral-typescript": "7.0.1",
"eslint": "8.29.0",
"eslint-config-ringcentral-typescript": "7.0.3",
"husky": "7.0.4",
"lerna": "4.0.0",
"lint-staged": "11.1.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/demo-page/src/components/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import reducer, {State} from './reducer';
export const makeStore = (context: Context) => {
const store = createStore(reducer, applyMiddleware(logger));

if (module.hot) {
module.hot.accept('./reducer', () => {
if ((module as any).hot) {
(module as any).hot.accept('./reducer', () => {
console.log('Replacing reducer');
store.replaceReducer(require('./reducer').default);
});
Expand Down
4 changes: 1 addition & 3 deletions packages/demo-page/src/pages/_error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ const ErrorPage = ({page}: any) => (
<>
<p>This is an error page, {page}.</p>
<nav>
<Link href="/">
<a>Navigate to index</a>
</Link>
<Link href="/">Navigate to index</Link>
</nav>
</>
);
Expand Down
8 changes: 2 additions & 6 deletions packages/demo-page/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@ const Page: NextPage<ConnectedPageProps> = ({custom}) => {
return (
<div className="index">
<pre>{JSON.stringify({page, custom}, null, 2)}</pre>
<Link href="/other">
<a>Navigate</a>
</Link>
<Link href="/other">Navigate</Link>
{' | '}
<Link href="/error">
<a>Navigate to error</a>
</Link>
<Link href="/error">Navigate to error</Link>
</div>
);
};
Expand Down
8 changes: 2 additions & 6 deletions packages/demo-page/src/pages/other.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ const OtherPage: NextPage<State> = () => {
<pre>{JSON.stringify({page}, null, 2)}</pre>
<nav>
<button onClick={bump}>bump</button>
<Link href="/">
<a>Navigate to index</a>
</Link>
<Link href="/other2">
<a>Navigate to other 2</a>
</Link>
<Link href="/">Navigate to index</Link>
<Link href="/other2">Navigate to other 2</Link>
</nav>
</div>
);
Expand Down
8 changes: 2 additions & 6 deletions packages/demo-page/src/pages/other2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ const OtherPage: NextPage<State> = () => {
<pre>{JSON.stringify({page}, null, 2)}</pre>
<nav>
<button onClick={bump}>bump</button>
<Link href="/">
<a>Navigate to index</a>
</Link>
<Link href="/other">
<a>Navigate to other</a>
</Link>
<Link href="/">Navigate to index</Link>
<Link href="/other">Navigate to other</Link>
</nav>
</div>
);
Expand Down
4 changes: 1 addition & 3 deletions packages/demo-page/src/pages/pageProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ const PropsPage: NextPage<State> = props => {
<p>Using Next.js default prop in a wrapped component.</p>
<pre>{JSON.stringify(props)}</pre>
<nav>
<Link href="/">
<a>Navigate to index</a>
</Link>
<Link href="/">Navigate to index</Link>
</nav>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/demo-redux-toolkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start": "next --port=6060"
},
"dependencies": {
"@reduxjs/toolkit": "1.6.2",
"@reduxjs/toolkit": "1.8.6",
"next-redux-wrapper": "*",
"react": "17.0.2",
"react-dom": "17.0.2",
Expand Down
69 changes: 69 additions & 0 deletions packages/demo-redux-toolkit/pages/detail/[id].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import {useDispatch, useSelector, useStore} from 'react-redux';
import Link from 'next/link';
import {InferGetServerSidePropsType, NextPage} from 'next';
import {
fetchDetail,
selectDetailPageData,
selectDetailPageId,
selectDetailPageStateTimestamp,
selectDetailPageSummary,
wrapper,
} from '../../store';

const Page: NextPage<InferGetServerSidePropsType<typeof getServerSideProps>> = ({serverTimestamp}) => {
console.log('State on render', useStore().getState());
console.log('Timestamp on server: ', serverTimestamp);
const dispatch = useDispatch();
const pageId = useSelector(selectDetailPageId);
const pageSummary = useSelector(selectDetailPageSummary);
const stateTimestamp = useSelector(selectDetailPageStateTimestamp);
const data = useSelector(selectDetailPageData);

console[pageSummary ? 'info' : 'warn']('Rendered pageName: ', pageSummary);

if (!pageSummary || !pageId || !data) {
throw new Error('Whoops! We do not have the pageId and pageSummary selector data!');
}

return (
<>
<div style={{backgroundColor: 'pink', padding: '20px'}}>Timestamp on server: {serverTimestamp}</div>
<div style={{backgroundColor: 'lavender', padding: '20px'}}>Timestamp in state: {stateTimestamp}</div>
<div className={`page${pageId}`}>
<h3>{pageSummary}</h3>
<Link href="/subject/1">Go id=1</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/subject/2">Go id=2</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/detail/1">Go to details id=1</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/detail/2">Go to details id=2</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/gipp">Go to gip page</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/pokemon/pikachu">Go to Pokemon</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/">Go to homepage</Link>
</div>
<button onClick={() => dispatch(fetchDetail(pageId))}>Refresh timestamp</button>
</>
);
};

export const getServerSideProps = wrapper.getServerSideProps(store => async ({params}) => {
const id = params?.id;
if (!id || Array.isArray(id)) {
throw new Error('Param id must be a string');
}

await store.dispatch(fetchDetail(id));

return {
props: {
serverTimestamp: new Date().getTime(),
},
};
});

export default Page;
47 changes: 47 additions & 0 deletions packages/demo-redux-toolkit/pages/gipp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import {useDispatch, useSelector, useStore} from 'react-redux';
import Link from 'next/link';
import {NextPage} from 'next';
import {fetchGipp, selectGippPageData, selectGippPageStateTimestamp, selectGippPageTestData, wrapper} from '../store';

const Page: NextPage = () => {
console.log('State on render', useStore().getState());
const dispatch = useDispatch();
const testData = useSelector(selectGippPageTestData);
const stateTimestamp = useSelector(selectGippPageStateTimestamp);
const data = useSelector(selectGippPageData);

console[testData ? 'info' : 'warn']('Rendered testData: ', testData);

if (!testData || !data) {
throw new Error('Whoops! We do not have the data and testData selector data!');
}

return (
<>
<div style={{backgroundColor: 'lavender', padding: '20px'}}>Timestamp in state: {stateTimestamp}</div>
<div className={`page${1}`}>
<h3>{testData}</h3>
<Link href="/subject/1">Go id=1</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/subject/2">Go id=2</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/detail/1">Go to details id=1</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/detail/2">Go to details id=2</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/pokemon/pikachu">Go to Pokemon</Link>
&nbsp;&nbsp;&nbsp;&nbsp;
<Link href="/">Go to homepage</Link>
</div>
<button onClick={() => dispatch(fetchGipp())}>Refresh timestamp</button>
</>
);
};

Page.getInitialProps = wrapper.getInitialPageProps(store => async () => {
await store.dispatch(fetchGipp());
return {};
});

export default Page;
16 changes: 14 additions & 2 deletions packages/demo-redux-toolkit/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ export default function IndexPage() {
You can see &quot;Rendered content: undefined&quot; in browser console after navigating between these pages:
<br />
<br />
<Link href="/subject/1">
<a>Go to problem pages</a>
<Link href="/subject/1" prefetch={false}>
Go to problem pages
</Link>
<br />
<Link href="/detail/1" prefetch={false}>
Go to detail pages
</Link>
<br />
<Link href="/gipp" prefetch={false}>
Go to gipp page
</Link>
<br />
<Link href="/pokemon/pikachu" prefetch={false}>
Go to Pokemon
</Link>
</div>
);
Expand Down
Loading

0 comments on commit 3822c94

Please sign in to comment.