所以我试图解决我在使用时面临的保湿问题wrapper.getServerSideProps
。当我使用当前设置重新路由时,存储被清除,然后添加新数据,这导致一个白页,因为许多重要数据不再存在(即翻译和 cms 数据)。
redux-dev-tools 的屏幕截图 Hydrate 操作差异:
从主页路由到产品页面后截取屏幕截图,因此存在现有商店。一切都重置为初始应用程序状态。
我想要做什么
在 store.js 中,我创建了 store 并预见了一个 reducer 来处理 Hydrate 调用。这种方法的缺点是有效负载将始终是一个新的存储对象,因为它是在服务器上调用的。我正在考虑检查 2 个 json 之间的差异,然后只应用差异而不是整个初始存储。
- 获取客户端和服务器状态之间的差异。
- 制作下一个状态,用修补过的服务器状态覆盖客户端状态,因此这包括来自 hydra 的更新状态和现有客户端状态。
- 当前结果是一个白页。
你可以在 store.js 中看到下面的 reducer 代码
//store.js
import combinedReducer from './reducer';
const bindMiddleware = (middleware) => {
if (process.env.NODE_ENV !== 'production') {
return composeWithDevTools(applyMiddleware(...middleware));
}
return applyMiddleware(...middleware);
};
const reducer = (state, action) => {
if (action.type === HYDRATE) {
const clientState = { ...state };
const serverState = { ...action.payload };
if (state) {
// preserve state value on client side navigation
// Get the difference between the client and server state.
const diff = jsondiffpatch.diff(clientState, serverState);
if (diff !== undefined) {
// If there is a diff patch the serverState, with the existing diff
jsondiffpatch.patch(serverState, diff);
}
}
// Make next state, overwrite clientstate with patched serverstate
const nextState = {
...clientState,
...serverState,
};
// Result, blank page.
return nextState;
}
return combinedReducer(state, action);
};
export const makeStore = () => {
const cookies = new Cookies();
const client = new ApiClient(null, cookies);
const middleware = [
createMiddleware(client),
thunkMiddleware.withExtraArgument(cookies),
];
return createStore(reducer, bindMiddleware(middleware));
};
const wrapper = createWrapper(makeStore);
export default wrapper;
//_app.jsx
const App = (props) => {
const { Component, pageProps, router } = props;
return (
<AppComponent cookies={cookies} locale={router.locale} location={router}>
<Component {...pageProps} />
</AppComponent>
);
};
App.getInitialProps = async ({ Component, ctx }) => {
return {
pageProps: {
...(Component.getInitialProps ? await Component.getInitialProps(ctx) : {}),
},
};
};
App.propTypes = {
Component: PropTypes.objectOf(PropTypes.any).isRequired,
pageProps: PropTypes.func,
router: PropTypes.objectOf(PropTypes.any).isRequired,
};
App.defaultProps = {
pageProps: () => null,
};
export default wrapper.withRedux(withRouter(App));
// Product page
export const getServerSideProps = wrapper.getServerSideProps(
async ({ query, store: { dispatch } }) => {
const productCode = query.id?.split('-', 1).toString();
await dispatch(getProductByCode(productCode, true));
});
const PDP = () => {
const { product } = useSelector((state) => state.product);
return (
<PageLayout>
<main>
<h1>{product?.name}</h1>
<div
className="description"
dangerouslySetInnerHTML={{ __html: product?.description }}
/>
</main>
</PageLayout>
);
};
export default PDP;