fayeah / blogs

方法论、问题驱动、总结
6 stars 0 forks source link

【React】如何避免effect hook的死循环 #37

Open fayeah opened 4 years ago

fayeah commented 4 years ago

hook是react16+的新特性,解决了逻辑复用等很多问题,使得我们能在函数是组件中使用state等特性。但是一旦用不好就很容易造成死循环。这里看2个例子以及如何解决。 根据文档: when you want some code to be executed after every render

当没有dependency

const [count, setCount] = useState(0)为例

image

如何解决

如果我们只想要count增加一次那么,加一个空的依赖即可

 useEffect(() => {
    setCount(100);
  }, []);

对于有些情况,我们希望根据state的变化而执行useEffect hook,那么我们可以加响应的dependency

useEffect(() => {
    const getData = async () => {
      const response = await fetch(`https://xxxx/api/people/${props.id}/`);
      const newData = await response.json();
      setData(newData);
    };
    getData();
  }, [props.id]);

这样就能解决死循环的问题,因为如果没有[props.id],跟上述死循环的逻辑是一样的。这样就能根据我们需要的id去获取,当id发生变化之后重新执行fetch的操作。

添加了dependency还是有问题

对于count的问题,尝试添加dependency,当count变化的时候再去执行 hook,但是还是有问题

const [count, setCount] = useState({a: 9});

  useEffect(() => {
    setCount({a: 100});
  }, [count]);

return (
    <div>
      <p>Count: {JSON.stringify(count)}</p>
    </div>
  );

那是因为对于引用类型object,每次都会产生新的id,那么相当于每次count都发生了变化,即便setCount的值看上去是静态数据。但是每次赋的值都是新的object。所以这个时候我们可以使用JSON.stringify(count)来解决:

const [count, setCount] = useState({a:0});

  useEffect(() => {
    setCount({a: 100});
  }, [JSON.stringify(count)]);

  return (
    <div>
      <p>Count: {count.a}</p>
    </div>
  );