代码之家  ›  专栏  ›  技术社区  ›  Joji

React:如何摆脱这个最大更新深度超过错误

  •  0
  • Joji  · 技术社区  · 4 年前

    我有一个组件,它的状态是一个对象,我想在 useEffect 在那里它循环遍历对象的键以更新状态。问题是,对于无限循环,它给了我一个错误。

    未捕获错误:超过最大更新深度。当 组件在componentWillUpdate或 componentDidUpdate。React将嵌套更新的数量限制为 防止无限循环。

    我想这是因为我使用的密钥列表 dep 使用效果 是一个数组,每次组件重新渲染时都不同,因为它不是基元类型。所以我用 useMemo 但它仍然不起作用,然后我意识到这可能是因为备忘录 dep 是状态,它也不是原始类型,即对象,因此每次都不同,导致每次键列表都不同,即使使用 使用备忘录

    这是代码

    const ManageIndexingPage: React.FC = () => {
      const dispatch = useDispatch();
      const stateFromStore = useSelector(
        (state: RootState) => state.settings.indexing
      );
      const [indexingConfig, setIndexingConfig] = useState<IndexingConfig>(
        getDefaultIndexingConfig()
      );
    
      const listOfKeys = useMemo(
        () => Object.keys(indexingConfig) as Array<keyof typeof indexingConfig>,
        [indexingConfig]
      );
    
      useEffect(() => {
        dispatch(getIndexingConfig());
      }, [dispatch]);
    
      useEffect(() => {
        listOfKeys.forEach((key) =>
          setIndexingConfig((prevState) => ({
            ...prevState,
            [key]: stateFromStore[key]
          }))
        );
      }, [stateFromStore, listOfKeys]);
    };
    
    //....
    
    function getDefaultIndexingConfig(): IndexingConfig {
      return {
        thingIndexingEnabled: false,
        thingConnectivityEnabled: false,
        thingDeviceShadowEnabled: false,
        thingGroupIndexingEnabled: false
      };
    }
    

    在这里 listOfkeys 实际上只是一个字符串数组,即。 ["thingIndexingEnabled", "thingConnectivityEnabled"...] 。因此,如果我将其硬编码并在中使用 使用效果 不会有这个错误,这很好 即

    useEffect(() => {
        ["thingIndexingEnabled", "thingConnectivityEnabled"...].forEach((key) =>
          setIndexingConfig((prevState) => ({
            ...prevState,
            [key]: stateFromStore[key]
          }))
        );
      }, [stateFromStore]);
    

    在不硬编码密钥列表的情况下,我应该如何消除这个错误?或者有更好的方法吗?

    1 回复  |  直到 4 年前
        1
  •  1
  •   MD10    4 年前

    问题在于:

     useEffect(() => {
       ....
          setIndexingConfig((prevState) => ({
            ...prevState,
            [key]: stateFromStore[key]
          }))
        );
      }, [stateFromStore, listOfKeys]);
    

    你不应该设置State useEffect() 因为这取决于每次更改都会导致useEffect再次执行。 set来自另一个地方的状态或使用useRef,因为它不会导致重新执行。