[英]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.