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

新手上路,请多包涵

我正在构建一个 Next.js 应用程序,它目前正在使用 Redux。在构建它时,我想知道是否真的有必要使用 Redux,以及它的使用是否实际上是一种反模式。这是我的推理:

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

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

我的问题是:

  1. 在这种情况下,Redux 存储有什么好处?
  2. 我应该在根目录中初始化存储 App 组件并放弃自动静态优化吗?
  3. 有没有更好的方法来管理 Next.js 9.3 中的状态 getStaticProps其他数据获取方法
  4. 我错过了什么吗?

原文由 Jamie S 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

如果您有一个带有 getInitialProps 的自定义应用程序,那么 Next.js 提供的自动静态优化将为所有页面禁用。

没错,如果您遵循这种方法。

有没有更好的办法 ?

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

例子:

 const IndexPage = () => {
  // Implementation
  const dispatch = useDispatch()
  // ...
  // ...
  return <Something />;
}

IndexPage.getInitialProps = ({ reduxStore }) => {
  // Implementation
  const { dispatch } = reduxStore;
  // ...
  // ...
}

export default withRedux(IndexPage)

您现在可以仅将 Redux 用于需要状态管理的页面,而无需禁用整个 App 的优化。

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

不可以,但需要正确使用。

有关如何在此处完成的更多信息: https ://github.com/vercel/next.js/tree/canary/examples/with-redux

我希望这有帮助

原文由 ddon-90 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

1- 在组件之间传递数据。

如果你不使用 redux,那么你需要做 prop drilling。为了确定用户是否登录,我们获取数据并将其存储在 redux store 中,然后 Header 组件连接到 store 并获取身份验证信息。如果你没有使用 redux,那么你需要在每个页面中获取用户,然后将其传递给 Header 组件。

Next.js 预渲染每个页面。这意味着 Next.js 会提前为每个页面生成 HTML,而不是全部由客户端 JavaScript 完成。预渲染可以带来更好的性能和 SEO。 next-redux-wrapper 包允许您将 redux 与自动静态优化一起使用。如果你点击链接,会有一条注释说:“Next.js 在使用 class MyApp extends App 时提供通用的 getInitialProps ,这将被包装器拾取,所以你不能扩展 App,因为你将被选择退出 Automatic Static优化:”。我为我的项目设置了这个包,它很容易设置。

但是使用 redux 的缺点是它没有缓存。您存储数据,然后定期重新获取数据以确保它是最新的。这是一项额外昂贵的工作。在redux中实现缓存,我们使用 reselect 库。这意味着你的项目在 redux 之上有额外的依赖,并且会让你写更多的代码。

有一个很好的包 swr ,它是由 next.js 创建的。陈旧而重新生效。它首先从缓存中返回数据(陈旧的),然后发送获取请求,最后再次带来更新的数据。我选择在每个页面中使用它。

 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;
      }
    }
  );

2- 发出 api 请求。

我为我的项目设置了 redux store,它与我设置的文本编辑器冲突。 Redux 以某种方式阻止了编辑器,我无法用我在编辑器上写的文本填充商店。所以我使用可重用的钩子来获取 api。一开始它看起来很刺激,但如果你分析它,它就会有意义。

 export function useApiHandler(apiCall) {
  // fetching might have one those 3 states. you get error, you fetch the data, and you start with the loading state
  const [reqState, setReqState] = useState({
    error:null,
    data:null,
    loading:true, // initially we are loading
  });
  const handler = async (...data) => {
    setReqState({ error: null, data: null, loading: true });
    try {
      // apiCall is a separate function to fetch the data
      const res = await apiCall(...data);
      setReqState({ error: null, data: res.data, loading: false });
      alert(res.data);// just to check it
      return res.data;
    } catch (e) {
      // short circuting in or. if first expression is true, we dont evaluate the second.
      // short circuting in and. if first expression is true, result is the second expression
      const message =
        (e.response && e.response.data) || "Ooops, something went wrong...";
      setReqState({ error: message, data: null, loading: false });
      return Promise.reject(message);
    }
  };

  return [handler, { ...reqState }];
}

一个简单的 apiCall 函数

  const createBlog = (data) => axios.post("/api/v1/blogs", data);

然后这就是我们使用它的方式:

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

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

Redux 工具包查询

我认为 redux toolkit query (RTK query) 是 redux 生态系统中最大的改进。它实际上建立在 redux-toolkit 库之上。 redux-toolkit 通过在幕后使用 immer.js 帮助我们编写更简单的 redux 代码并更轻松地更新状态。

使用“RTK 查询”,我们可以一起处理数据获取和状态管理。所有的数据获取都结合在一个 API 下,我们可以缓存数据、使缓存无效或重新获取查询。它实际上正在做 swrcontext Api 的组合正在做的事情。 使用 swr 和 context api 进行状态管理

原文由 Yilmaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题