简体   繁体   English

将 NextJS 与 Redux 一起使用。 是否应该在具有不同预加载状态的页面之间重新初始化存储?

[英]Using NextJS with Redux. Should the store be re-initialised between pages with different preloaded states?

I'm trying to make Redux work with NextJS.我正在尝试使 Redux 与 NextJS 一起使用。 In the official NextJS repo, you can find the following example:在 NextJS 官方 repo 中,您可以找到以下示例:

https://github.com/vercel/next.js/tree/canary/examples/with-redux-thunk https://github.com/vercel/next.js/tree/canary/examples/with-redux-thunk

Here is the main part of the Redux code (the one that initialises the store).这是 Redux 代码(初始化存储的代码)的主要部分。

import { useMemo } from 'react'
import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'
import reducers from './reducers'

let store

function initStore(initialState) {
  return createStore(
    reducers,
    initialState,
    composeWithDevTools(applyMiddleware(thunkMiddleware))
  )
}

export const initializeStore = (preloadedState) => {
  let _store = store ?? initStore(preloadedState)

  // After navigating to a page with an initial Redux state, merge that state
  // with the current state in the store, and create a new store
  if (preloadedState && store) {
    _store = initStore({
      ...store.getState(),
      ...preloadedState,
    })
    // Reset the current store
    store = undefined
  }

  // For SSG and SSR always create a new store
  if (typeof window === 'undefined') return _store
  // Create the store once in the client
  if (!store) store = _store

  return _store
}

export function useStore(initialState) {
  const store = useMemo(() => initializeStore(initialState), [initialState])
  return store
}

Here is what they say about it:他们是这样说的:

Every initial server-side request will utilize a new store.每个初始的服务器端请求都将使用一个新的存储。 However, every Router or Link action will persist the same store as a user navigates through the pages.但是,每个 Router 或 Link 操作都将在用户浏览页面时保留相同的存储。 To demonstrate this example, we can navigate back and forth to /show-redux-state using the provided Links.为了演示这个示例,我们可以使用提供的链接来回导航到 /show-redux-state。 However, if we navigate directly to /show-redux-state (or refresh the page), this will cause a server-side render, which will then utilize a new store.但是,如果我们直接导航到 /show-redux-state(或刷新页面),这将导致服务器端渲染,然后将使用新的存储。

Their full example is not a very good one, because none of the pages use the getInitialProps method.他们的完整示例不是一个很好的示例,因为没有一个页面使用getInitialProps方法。 So you can't see the store changing when you switch pages.因此,您在切换页面时看不到store的变化。

// Create the store once in the client

From the comment above, I was under the impression that, no matter what, a store would only be initialised once (a single time) in the client.从上面的评论中,我的印象是,无论如何,商店只会在客户端初始化一次(一次) But that is not the case.但事实并非如此。

Every time I navigate to a page that adds a initialState to the Redux store (this is done by using the getInitialProps method), a get a new store on my client code.每次我导航到一个将initialState添加到 Redux 存储的页面(这是通过使用getInitialProps方法完成的)时,都会在我的客户端代码上获取一个新存储。 I've literally tested this behaviour.我已经从字面上测试了这种行为。 The store reference does change. store引用确实发生了变化。

And that got me thinking: isn't mutating the Redux store references across multiple renders, a bad practice?这让我想到:在多个渲染中改变 Redux store引用不是一种不好的做法吗? I mean, React will re-render accordingly, but what about async code?我的意思是,React 会相应地重新渲染,但是异步代码呢?

Let's say I have a Redux thunk that still pending and I navigate away from the page.假设我有一个 Redux thunk 仍然挂起,我导航离开页面。 Now, my Redux store will be re-initialised and what will happen if:现在,我的 Redux 存储将被重新初始化,如果:

  • My thunk dispatch new actions?我的 thunk 派发新动作? The dispatch that the thunk has is most likely linked to the previous store thunk 的调度很可能链接到以前的商店
  • My thunk accesses getState() ?我的 thunk 访问getState() That getState() call is also probably linked to the previous store.getState()调用也可能链接到以前的商店。

Is this an anti-pattern or what?这是反模式还是什么?

I don't have a final answer if this is an anti-pattern or not, but there's definitely a limitation with the way NextJS suggests that the store should be initialised and re-initialised to merge server data.如果这是否是反模式,我没有最终答案,但是 NextJS 建议应初始化并重新初始化存储以合并服务器数据的方式肯定存在限制。

I just ran the following test:我刚刚进行了以下测试:

_app.tsx _app.tsx

import { useEffect } from "react";
import { Provider } from "react-redux";
import { useStore } from "./useStore";

export default function App({ Component, pageProps }) {
  console.log("Rendering App...");

  const store = useStore(pageProps.initialReduxState);
  const dispatch = store.dispatch;
  const getState = store.getState;

  useEffect(() => {
    console.log("store has changed");
  }, [store]);

  useEffect(() => {
    console.log("dispatch has changed");
  }, [dispatch]);

  useEffect(() => {
    console.log("getState has changed");
  }, [getState]);

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

When I navigate to pages without any pageProps.initialReduxState value, here is what I get:当我导航到没有任何pageProps.initialReduxState值的页面时,我得到的是:

在此处输入图像描述

When I navigate to pages with pageProps.initialReduxState value, here is what happens:当我导航到具有pageProps.initialReduxState值的页面时,会发生以下情况:

在此处输入图像描述

As a result from this test, I think it's safe to assume that pending code running inside a thunk will be stale and won't have any effect on the new store.作为这个测试的结果,我认为可以安全地假设在 thunk 中运行的待处理代码将是陈旧的,并且不会对新存储产生任何影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 useState 中的默认值未重新初始化 - Default value in useState not getting re-initialised 我正在使用 Redux。 我应该在 Redux 存储中管理受控输入状态还是在组件级别使用 setState? - I am using Redux. Should I manage controlled input state in the Redux store or use setState at the component level? 为什么我的自定义钩子没有在路径更改时重新初始化? - Why is my custom hook not re-initialised on path change? 区别:MobX 和 Redux。 - Difference between: MobX and Redux. NextJS 和 Redux 更改页面时清除存储 - NextJS and Redux clearing store when changing pages 我如何在 react redux 中访问另一个 reducer 的状态。 reducer 和 store 之间的状态流 - How do i access state of one reducer in other in react redux. State flow between reducers and store React-Redux:是否应该将所有组件状态保存在 Redux Store 中 - React-Redux: Should all component states be kept in Redux Store redux商店应该只保留非UI状态吗? - Should the redux store keep only non-UI states? ReactJS 使用 Hooks 和 Redux 的良好做法。 我应该在每个组件中使用 useSelector,还是应该通过 props 传递? - ReactJS good practices using Hooks and Redux. Should I use useSelector in each component, or I should pass via props? 如何使用 next-redux-wrapper 在 nextjs 页面之间共享 state? - How to share state between nextjs pages with next-redux-wrapper?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM