You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Context出现最大更新深度超限问题,求解决方案

这问题我之前也碰到过,核心原因就是你触发了无限渲染循环,咱们一步步理清楚怎么解决:

问题根源

你在Mats组件的渲染过程中直接调用了getProductCategory("mats"),而这个函数里又调用了setProductCategory——这个setState会触发ProductContextProvider的状态更新,进而导致所有消费这个Context的组件(包括Mats)重新渲染。重新渲染时又会再次调用getProductCategory,再次触发setState,循环就这么形成了,直到React触发最大更新深度的报错。


方案一:移除不必要的Context状态(推荐)

其实你根本不需要在Context里维护productsCategory这个状态,因为Mats组件只是需要过滤后的结果,没必要把它存在Context的状态中。直接修改Context里的getProductCategory函数,让它直接返回过滤好的数据就行:

修改后的ProductContextProvider代码:

import React, { createContext, useState, useEffect } from "react";
import data from "./data";
export const ProductContext = createContext();
const ProductContextProvider = ({ children }) => {
  const [products, setProducts] = useState();
  
  // 给useEffect加空依赖数组,只执行一次初始化
  useEffect(() => {
    setProducts(data);
  }, []);

  function getProductCategory(category) {
    // 直接返回过滤后的结果,无需触发状态更新
    return data.filter((product) => product.type === category);
  }

  const getProduct = (product) => {
    const currentProduct = products ? products.filter((item) => item.slug === product)[0] : undefined;
    return currentProduct;
  };

  return (
    <ProductContext.Provider value={{ getProduct, getProductCategory }} >
      {children}
    </ProductContext.Provider>
  );
};
export default ProductContextProvider;

Mats组件不需要修改,这样调用getProductCategory("mats")就只是一个纯函数调用,不会触发状态更新,自然就不会有循环了。


方案二:如果必须维护Context状态,用useEffect触发更新

如果你确实需要在Context里保留productsCategory的状态(比如其他组件也要复用这个数据),那就在Mats组件里用useEffect来调用getProductCategory,只在组件挂载时执行一次:

修改后的Mats组件:

import React, { useContext, useEffect, useState } from "react";
import { ProductContext } from "../../context";
import CategoryTitle from "./accesoriesComponent/CategoryTitle/CategoryTitle"; // 顺便修正你之前写错的import路径
import Filters from "../../components/accesoriesComponent/Filters/Filters";
import ProductWrapper from "../../components/accesoriesComponent/ProductWrapper/ProductWrapper";

export default function Mats(props) {
  const { getProductCategory } = useContext(ProductContext);
  const [mats, setMats] = useState([]);

  useEffect(() => {
    // 只在组件挂载时调用一次
    const categoryProducts = getProductCategory("mats");
    setMats(categoryProducts);
  }, [getProductCategory]); // 加上依赖,确保函数变化时重新执行

  return (
    <div>
      <div style={{ display: "flex" }}>
        <Filters />
        {mats.length > 0 && <ProductWrapper products={mats} />}
      </div>
    </div>
  );
}

同时,Context里的getProductCategory要调整一下,直接返回刚过滤的结果(因为setState是异步的,原来返回的productsCategory可能是旧值):

function getProductCategory(category) {
  const productFromCategory = data.filter(
    (product) => product.type === category
  );
  setProductCategory(productFromCategory);
  console.log(productFromCategory);
  return productFromCategory; // 返回最新过滤结果,而非状态中的值
}

另外还要提醒你:Provider里的useEffect原本没有依赖数组,会每次渲染都执行setProducts(data),虽然data是静态的,但最好加上空数组[],避免不必要的重复执行,我在方案一的代码里已经做了这个修正。

内容的提问来源于stack exchange,提问作者Sebastian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:45:42