import React from'react'import{Provider}from'react-redux'import{initializeStore}from'../store/store'import App from'next/app'// 返回一个高阶组件,将store传递给包裹的组件exportconstwithRedux=(PageComponent,{ssr =true}={})=>{constWithRedux=({initialReduxState,...props})=>{const store =getOrInitializeStore(initialReduxState);return(<Provider store={store}><PageComponent {...props}/></Provider>)};// Make sure people don't use this HOC on _app.js levelif(process.env.NODE_ENV!=='production'){const isAppHoc =
PageComponent === App || PageComponent.prototype instanceofApp;if(isAppHoc){thrownewError('The withRedux HOC only works with PageComponents')}}// Set the correct displayName in developmentif(process.env.NODE_ENV!=='production'){const displayName =
PageComponent.displayName || PageComponent.name ||'Component';
WithRedux.displayName =`withRedux(${displayName})`}if(ssr || PageComponent.getInitialProps){
WithRedux.getInitialProps =async context =>{// Get or Create the store with `undefined` as initialState// This allows you to set a custom default initialStateconst reduxStore =getOrInitializeStore();// Provide the store to getInitialProps of pages
context.reduxStore = reduxStore;// Run getInitialProps from HOCed PageComponentconst pageProps =typeof PageComponent.getInitialProps ==='function'?await PageComponent.getInitialProps(context):{};// Pass props to PageComponentreturn{...pageProps,
initialReduxState: reduxStore.getState()}}}return WithRedux
};let reduxStore;constgetOrInitializeStore= initialState =>{// Always make a new store if server, otherwise state is shared between requestsif(typeof window ==='undefined'){returninitializeStore(initialState)}// Create store if unavailable on the client and set it on the window objectif(!reduxStore){
reduxStore =initializeStore(initialState)}return reduxStore
};
使用
import React from'react'import{ withRedux }from'../lib/with-redux'constIndexPage=(props)=>{
console.log(props.counter);return(<><span>test redux,{props.counter.lastUpdate}</span></>)};
IndexPage.getInitialProps=({ reduxStore })=>{// Tick the time once, so we'll have a// valid time before first renderconst{ dispatch }= reduxStore;dispatch({
type:'TICK',
light:typeof window ==='object',
lastUpdate: Date.now()});return reduxStore.getState()};exportdefaultwithRedux(IndexPage)