为什么useEffect不会在每个渲染上触发?

问题描述 投票:2回答:2

我的组件有两个Rect.useEffect

const Example = ({ user }) => {
  React.useEffect(() => {
    autorun(() => {
      console.log("inside autorun", user.count);
    });
  });

  // Only runs once
  React.useEffect(() => {
    console.log("Why not me?");
  });

  return <Observer>{() => <h1>{user.count}</h1>}</Observer>;
};

我使用mobx更新此组件。它被正确地重新渲染。但"Why not me?"只打印一次。

根据official docs

默认情况下,效果在每次完成渲染后运行

这意味着console.log("Why not me?");也应该在每次更新prop user时运行。但事实并非如此。控制台输出就是这个

这种明显不一致背后的原因是什么?

我的完整代码可以在这里查看

Edit mobx-useEffect query

reactjs react-hooks mobx-react
2个回答
3
投票

在Mobx中,就像提供渲染函数回调的Observer组件一样,autorun函数也独立于反应生命周期执行。

出现这种情况是因为您将用户计数作为可观察变量。

根据mobx-react文档

Observer是一个React组件,它将observer应用于组件中的匿名区域。它需要一个单独的,无参数的函数,它应该只返回一个React组件。将跟踪函数中的渲染并在需要时自动重新渲染。

和mobx文档

当使用autorun时,提供的函数将始终立即触发一次,然后每次其依赖项之一发生更改时再次触发。

您可以通过直接在功能组件内部进行记录来确认此行为,并且您将观察到该组件仅呈现一次

编辑:

回答你的问题

如果我改变useEffect

React.useEffect(autorun(() => {console.log("inside autorun", user.count)}));

基本上从useEffect中删除匿名函数并直接传递autorun,然后它只运行一次。为什么会这样?有什么不同?

不同的是,autorun返回一个disposer function,在运行时将处置autorun并且不再执行它。

来自文档:

autorun的返回值是一个处理器函数,可用于在不再需要时处理自动运行。

现在发生的事情是,因为useEffect在运行时执行提供给它的回调,所以执行的回调是autorun返回的disposer函数,它基本上取消了你的自动运行。


1
投票

看起来您的组件不会重新渲染。 autorun收到一个回调,可能会独立于渲染调用它。

Example组件只有在其父级重新渲染或其道具发生变化时才会重新渲染。

使用此代码观察实际发生的情况:

const Example = ({ user }) => {
  console.log('render');
  React.useEffect(() => {
    console.log('useEffect autorun');
    autorun(() => {
      console.log("inside autorun", user.count);
    });
  });

  // Only runs once
  React.useEffect(() => {
    console.log("Why not me?");
  });

  return <Observer>{() => <h1>{user.count}</h1>}</Observer>;
};
© www.soinside.com 2019 - 2024. All rights reserved.