繁体   English   中英

使用 Zustand 无限重新渲染

[英]Infinite re-render using Zustand

我来自 redux + redux-saga 和 class 组件,在 class 组件中使用 componentDidMount 时一切顺利。 获取 api 的调度操作运行良好,无需重复请求。

学习功能组件有一段时间了,决定用 Zusand 代替我的 redux-saga 来处理我的 state 管理流程。 我可以通过调用动作创建者在减速器中设置 state A 从 state B 和 state 得到更新。

首先,这是我到目前为止的反应功能组件代码:

首页集装箱

 import { useEffect } from "react"; import { appStore } from "../App/store"; export default function HomeContainer(props: any): any { const getCarouselData = appStore((state: any) => state.getCarousels); const carousels = appStore((state: any) => state.carousels); useEffect(() => { if (carousels.length === 0) { getCarouselData(); } }, [carousels, getCarouselData]); console.log("carousels", carousels); return <p>Home Container</p>; } Loading Slice

 const loadingSlice = (set: any, get: any) => ({ loading: false, setLoading: (isLoading: boolean) => { set((state: any) => ({...state, loading: isLoading })); }, }); export default loadingSlice;

应用商店

 import create from "zustand"; import homeSlice from "../Home/store"; import loadingSlice from "../Layout/state"; export const appStore = create((set: any, get: any) => ({...loadingSlice(set, get),...homeSlice(set, get), }));

来到 Zusand,它的行为似乎与 Redux 不同。 我正在尝试使用以下代码更新加载指示器的 boolean 值:

 import create, { useStore } from "zustand"; import axios from "axios"; import { appStore } from "../App/store"; const homeSlice = (set: any, get: any) => ({ carousels: [], getCarousels: () => { appStore.getState().setLoading(true); axios.get("api-endpoint").then((res) => { set((state: any) => ({...state, carousels: res.data, })); }).catch((err) => { console.log(err); }); appStore.getState().setLoading(true); }, }); export default homeSlice;

state 正在更改,对话框正在显示,但组件会继续重新渲染,直到超过最大更新深度。 我不知道为什么会这样。 如何在不重新渲染组件的情况下从 state 中的方法更新 state?

任何帮助都感激不尽。 谢谢你。

更新

getCarousels 的新实例由于调度而没有创建,因为只调用了一次创建回调来设置初始 state,然后在此 state 上进行更新。

原始答案

您的全球减速机在每次调度时调用homeSlice(set, get) (通过set . 此调用创建一个新的getCarousels实例,该实例作为依赖项传递到您的useEffect数组中,从而导致无限重新渲染。

您的HomeContainer将调用初始getCarousels ,它调用setLoading将触发 state 更新(通过set )并带有新的getCarousels 正在更新的 state 将导致appStore挂钩重新渲染HomeContainer组件,其中getCarousels的新实例在无限循环中再次触发效果。

这可以通过从 useEffect 依赖数组中删除getCarouselsData或使用 ref 来存储它(如Zusstand 自述文件中的示例)来解决:

  const carousels = appStore((state: any) => state.carousels);
  const getCarouselsRef = useRef(appStore.getState().getCarousels)
  useEffect(() => appStore.subscribe(
    state => (getCarouselsRef.current = state.getCarousels)
  ), [])
  useEffect(() => {
    if (carousels.length === 0) {
      getCarouselsRef.current();
    }
  }, [carousels]); // adding getCarouselsRef here has no effect

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM