将Redux与Next.js一起使用是一种反模式吗?

将Redux与Next.js一起使用是一种反模式吗?,redux,react-redux,next.js,Redux,React Redux,Next.js,我正在构建一个Next.js应用程序,它目前正在使用Redux。在构建它的过程中,我想知道是否真的需要使用Redux,以及它的使用是否实际上是一种反模式。我的理由如下: 为了在Next.js中正确初始化Redux存储,您必须使用getInitialProps方法创建一个自定义App组件。通过这样做,您将禁用Next.js提供的 相比之下,如果我只在安装应用程序后才在客户端包含Redux,那么每次服务器端导航后,Redux存储都会重置。例如,我有一个Next.js应用程序在客户端初始化Redux存

我正在构建一个Next.js应用程序,它目前正在使用Redux。在构建它的过程中,我想知道是否真的需要使用Redux,以及它的使用是否实际上是一种反模式。我的理由如下:

为了在Next.js中正确初始化Redux存储,您必须使用
getInitialProps
方法创建一个自定义
App
组件。通过这样做,您将禁用Next.js提供的

相比之下,如果我只在安装应用程序后才在客户端包含Redux,那么每次服务器端导航后,Redux存储都会重置。例如,我有一个Next.js应用程序在客户端初始化Redux存储,但当路由到动态路由(如
pages/projects/[id]
)时,页面是服务器端呈现的,我必须重新获取存储中的任何信息

我的问题是:

  • 在这种情况下,Redux商店有什么好处
  • 我是否应该在root
    App
    组件中初始化存储并放弃自动静态优化
  • 使用
    getStaticProps
  • 我错过什么了吗
  • 如果您有一个带有getInitialProps的自定义应用程序,则自动 Next.js提供的静态优化将对所有用户禁用 页数

    是的,如果你遵循这种方法

    有更好的办法吗

    是的,您可以创建一个Redux提供程序作为包装器并包装您需要的组件,Redux上下文将自动初始化并在该组件中提供

    例如:

    const IndexPage = () => {
      // Implementation
      const dispatch = useDispatch()
      // ...
      // ...
      return <Something />;
    }
    
    IndexPage.getInitialProps = ({ reduxStore }) => {
      // Implementation
      const { dispatch } = reduxStore;
      // ...
      // ...
    }
    
    export default withRedux(IndexPage)
    
    constindexpage=()=>{
    //实施
    const dispatch=usedpatch()
    // ...
    // ...
    返回;
    }
    IndexPage.getInitialProps=({reduxStore})=>{
    //实施
    const{dispatch}=reduxStore;
    // ...
    // ...
    }
    使用Redux导出默认值(IndexPage)
    
    现在,您可以仅对需要状态管理的页面使用Redux,而不禁用整个应用程序的优化

    回答您的问题“将Redux与Next.js一起使用是一种反模式吗?”

    没有,但需要正确使用

    有关如何操作的更多信息,请参见此处:


    我希望这有帮助

    我们使用Redux主要有两个原因

    1-在组件之间传递数据。 如果不使用redux,则需要进行支柱钻孔。为了决定用户是否登录,我们获取数据,然后将其存储在redux存储中,然后头组件连接到存储并获取身份验证信息。如果不使用redux,则需要在每个页面中获取用户,然后将其传递给Header组件

    Next.js预先呈现每个页面。这意味着Next.js会提前为每个页面生成HTML,而不是由客户端JavaScript完成。预渲染可以带来更好的性能和SEO。软件包允许您将redux与自动静态优化一起使用。如果您单击该链接,会看到一条注释:“Next.js在使用类MyApp extends App时提供了通用的getInitialProps,这将由包装器拾取,因此您不能扩展应用程序,因为您将选择退出自动静态优化:”。我为我的项目设置了这个包,它很容易设置

    但使用redux的缺点是,它不是缓存。存储数据,然后定期重新蚀刻以确保数据是最新的。这是一项额外昂贵的工作。为了在redux中实现缓存,我们使用库。这意味着您的项目在redux之上有额外的依赖性,这将使您编写更多的代码

    有一个很好的包是由next.js创建的。重新验证时失效。它首先从缓存(stale)返回数据,然后发送获取请求,最后再次返回更新的数据。我选择在每页中使用此选项

    import useSWR from "swr";
    
    export const useGetUser = () => {
         // fetcher can be any asynchronous function which returns the data. useSwr will pass "/api/v1/me" to fetcher
         const { data, error, ...rest } = useSWR("/api/v1/me", fetcher);
         // !data && !error if both true, loading:true, data=null=>!data=true, error=null => !error=true
         return { data, error, loading: !data && !error, ...rest };
       };
    
    这是可恢复的抓取程序

    export const fetcher = (url: string) =>
      fetch(url).then(
        async (res: Response): Promise<any> => {
          const result = await res.json();
    
          if (res.status !== 200) {
            return Promise.reject(result);
          } else {
            return result;
          }
        }
      );
    
    一个简单的apiCall函数

      const createBlog = (data) => axios.post("/api/v1/blogs", data);
    
    然后这就是我们如何使用它:

      export const useCreateBlog = () => useApiHandler(createBlog);
    

    设置redux很容易,因为人们并不担心应用程序的性能,他们只是设置了redux。在我看来,如果你有一个大型应用程序,你需要设置redux,或者如果你熟悉graphql,你可以使用Apollo。这里有一篇很好的文章来了解如何使用阿波罗作为国家管理。我建立了一个大型电子商务网站,并在我的新应用程序中使用了redux,因为它相对较小,我不使用next js,使其更复杂。

    我个人认为使用redux在任何情况下都不是一个好主意。例如,最好使用useContext,或者在极度需要集中存储的情况下,使用mobx。但事实上,有一种简单的方法可以将Redux与SSR一起使用,而不必使用getInitialProps

    这里有一点很重要——我给出的解决方案仅适用于不使用服务器上每个页面的呈现的情况——在第一次呈现之后,应用程序按照路径呈现下一个页面。在该解决方案中,假定存储将在服务器端初始化一次,然后渲染结果将传输到客户端。如果每次导航路线时都需要在服务器上呈现页面,并且需要保存存储状态,那么您最好还是查看下一个redux包装器

    因此,要首先在getServerSideProps上初始化存储,您需要按如下所示更改存储初始化文件(可能会有其他导入):

    之后,在需要存储在getServerSideProps中服务器端的页面中,可以简单地使用initializeStore:

    import { initializeStore } from '@Redux';
    
    // Compnent code here...
    
    export const getServerSideProps(context: any) {
        const reduxStore = initializeStore();
        // reduxStore = {
        // dispatch: [Function (anonymous)],
        // subscribe: [Function: subscribe],
        // getState: [Function: getState],
        // }
    
        // Doing something with the storage...
    
        const initialReduxState = storeInstance.getState(); // and get it state
        return { props: { initialReduxState, ...someProps } };
    }
    
    另外,不要忘记,如果您需要在_app.js中访问商店,则必须将商店定义为:

    const store = initializeStore(pageProps.initialReduxState);
    
    import { initializeStore } from '@Redux';
    
    // Compnent code here...
    
    export const getServerSideProps(context: any) {
        const reduxStore = initializeStore();
        // reduxStore = {
        // dispatch: [Function (anonymous)],
        // subscribe: [Function: subscribe],
        // getState: [Function: getState],
        // }
    
        // Doing something with the storage...
    
        const initialReduxState = storeInstance.getState(); // and get it state
        return { props: { initialReduxState, ...someProps } };
    }
    
    const store = initializeStore(pageProps.initialReduxState);