简体   繁体   English

为什么这个反应钩子会导致无限循环?

[英]Why this react hook cause infinite loop?

This piece of code will run infinitely, but no matter removing the useValue(object) or useTest() will stop the infinite run.这段代码会无限运行,但是不管去掉useValue(object)还是useTest()都会停止无限运行。 This whole thing does not make sense to me, can somebody explain it?这整件事对我来说没有意义,有人可以解释一下吗?

https://codesandbox.io/s/zen-currying-v2zu1?file=/src/App.jshttps://codesandbox.io/s/zen-currying-v2zu1?file=/src/App.js

import React from "react";
import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  // this code can also stop the infinite loop

  // const [object] = useState({
  //   name: "",
  //   personId: ""
  // });
  const object = {
    name: "",
    personId: ""
  };
  // strange thing: remove useValue or useTest can stop the ifinite loop
  useValue(object);
  useTest();
  // this console will run infinitely
  console.log(object);
  return <div className="App">{"123"}</div>;
}

export const useTest = () => {
  const [a, setA] = useState(1);
  useEffect(() => {
    setA(2);
  }, []);
};

const useValue = (value) => {
  const [a, setA] = useState(value);
  useEffect(() => {
    setA(value);
  }, [value]);
  // return a
};

Make sure to memoize your object in order to properly use it in dependencies.确保记住您的 object 以便在依赖项中正确使用它。

const { useMemo } from 'react';

const object = useMemo(
  () => ({
    name: "",
    personId: ""
  }),
  []
);

The reason behind the infinite loop is because you're providing a non-memoized object into your dependency array in useEffect .无限循环背后的原因是因为您在 useEffect 的依赖数组中提供了一个非记忆的useEffect

Object comparison in Javascript is more complex than just comparing obj1 === obj2 , as there is a reference that needs to be taken into account. Javascript 中的 Object 比较比仅比较obj1 === obj2更复杂,因为需要考虑一个参考。

Read more about comparing objects in javascript here此处阅读有关比较 javascript 中的对象的更多信息

Because object is a reference type, its identity will change every time you rerender App .因为object是引用类型,所以每次重新渲染App时它的标识都会改变。 There you use a custom hook useValue and pass object into it.在那里,您使用自定义挂钩useValue并将object传递给它。 Since you also register it as value in the dependency array of useEffect , useEffect will be triggered, setting a new state, ending in rerendering and looping.由于您还在useEffect的依赖数组中将其注册为value ,因此将触发useEffect ,设置新的 state,以重新渲染和循环结束。

  1. Make sure, you save the identity of reference types ( useMemo or useCallback ).确保保存引用类型的标识( useMemouseCallback )。
  2. Read the docs about useEffect .阅读有关useEffect文档 Its behaviour strongly depends on how you use its dependency array.它的行为很大程度上取决于你如何使用它的依赖数组。

Because you passed an object in the dependencies.因为您在依赖项中传递了 object。 useEffect with do a shallow comparison so it always renders. useEffect with 做一个浅比较,所以它总是呈现。

There are some solutions.有一些解决方案。 Read here . 在这里阅读。 You could modify your useValue hook to use JSON.stringify as below.您可以修改您的 useValue 挂钩以使用 JSON.stringify,如下所示。

const useValue = (value) => {
    const [a, setA] = useState(value);
    useEffect(() => {
        setA(value);
    }, [JSON.stringify(value)]);
    // return a
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM