React中useEffect未触发依赖变更却在首次渲染执行的原因排查
问题:监听Context属性的useEffect为何在首次渲染时自动执行?
我正在处理一个useEffect逻辑,它监听来自Context API的属性变更,该属性仅在需要时才会被触发更新。但奇怪的是,组件首次渲染完成后,监听该属性的useEffect就自动执行了。
相关代码如下:
组件代码
const { getXlsProducts, xlsProducts } = useProducts() // context ... const xls = async() => { await getXlsProducts(1, 10) } useEffect(() => { // 该useEffect在首次渲染时自动调用 console.log('why?'); }, [xlsProducts]);
Context中的代码(从未在首次渲染时调用getXlsProducts,仅在需要时调用)
const [ xlsProducts, setXlsProducts] = useState([]) const getXlsProducts = async(page, limit) => { const LS = localStorage.getItem('cmtjs') const config = { headers: { "Content-Type": "application/json", apiKey: LS } , params: { page, limit } } try { const { data } = await axiosClient(`/products`, config) setXlsProducts(data) } catch (error) { console.log(error); } }
原因分析
这是React useEffect的默认行为:只要声明了带有依赖数组的useEffect,它就会在组件首次渲染完成后自动执行一次,之后仅在依赖项发生变化时再次触发。
你的xlsProducts在Context中初始值为[],组件首次渲染时会读取到这个初始状态,此时useEffect会因首次渲染的触发条件执行,和是否调用getXlsProducts无关——哪怕xlsProducts未被主动更新过,首次渲染的执行逻辑依然会触发。
如果要让这个useEffect仅在xlsProducts被主动更新(即调用getXlsProducts后的值变化)时执行,可以通过以下方式处理:
- 修改初始状态并添加判断:将
xlsProducts的初始值设为null而非[],在useEffect中跳过初始状态:
// Context中调整初始值 const [ xlsProducts, setXlsProducts] = useState(null) // 组件中调整useEffect逻辑 useEffect(() => { if (xlsProducts !== null) { // 跳过首次渲染的初始null状态 console.log('仅在主动更新后执行'); } }, [xlsProducts]);
- 新增加载状态标记:在Context中额外维护一个
isFirstLoad状态,初始为true,调用getXlsProducts后将其设为false,组件的useEffect结合该标记判断是否执行逻辑。
内容的提问来源于stack exchange,提问作者OscarDev
相关产品推荐
相关产品推荐

