使用Zustand导致React渲染循环问题求助
解决Zustand结合Immer时的
Maximum update depth exceeded错误 问题原因
你调用useResidentialStore时传入的选择器函数,每次都会返回一个全新的对象。Zustand默认通过引用比较判断状态是否变化,由于每次返回的对象引用不同,Zustand会误判状态更新,触发组件重渲染;重渲染时选择器又返回新对象,如此循环就导致了更新深度超限的错误。而单独获取单个值时,返回的是原始类型或稳定引用的对象,浅比较能识别出状态未变化,所以不会触发循环。
解决方案
1. 使用shallow比较器(推荐)
Zustand提供的shallow工具,可让选择器返回的对象通过浅比较判断变化,而非直接比较对象引用。
首先导入shallow:
import { create, shallow } from "zustand"
然后在使用store时传入shallow作为第二个参数:
const { minPrice, minPriceOptions, setMinPrice, } = useResidentialStore(state => ({ minPrice: state.minPrice, minPriceOptions: state.minPriceOptions, setMinPrice: state.setMinPrice, }), shallow)
2. 拆分多个useResidentialStore调用
既然单独取单个值无问题,可将解构拆分为多个独立调用:
const minPrice = useResidentialStore(state => state.minPrice) const minPriceOptions = useResidentialStore(state => state.minPriceOptions) const setMinPrice = useResidentialStore(state => state.setMinPrice)
3. 用useMemo缓存选择器(可选)
通过useMemo让选择器的引用保持稳定,避免每次渲染生成新函数:
import { useMemo } from "react" // 组件内 const selectResidentialData = useMemo(() => state => ({ minPrice: state.minPrice, minPriceOptions: state.minPriceOptions, setMinPrice: state.setMinPrice, }), []) const { minPrice, minPriceOptions, setMinPrice, } = useResidentialStore(selectResidentialData)
此方式不如shallow简洁,一般优先选择第一种方案。
验证修改效果
采用第一种方案的完整组件内代码示例:
import { useResidentialStore } from "../path-to-your-store-file" import { shallow } from "zustand" function YourComponent() { const { minPrice, minPriceOptions, setMinPrice, } = useResidentialStore(state => ({ minPrice: state.minPrice, minPriceOptions: state.minPriceOptions, setMinPrice: state.setMinPrice, }), shallow) // 组件逻辑... return <div>...</div> }
这样就能避免无意义的渲染循环,Zustand会通过浅比较准确判断状态是否真的更新。
内容的提问来源于stack exchange,提问作者Jerome Marshall
相关产品推荐
相关产品推荐

