为什么 useEffect 不会在每次渲染时都触发?

Why useEffect doesn't fire on every render?

我的组件有两个 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

By default, effects run after every completed render

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

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

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

您的组件似乎没有重新呈现。 autorun 收到回调并可能独立于渲染调用它。

Example 组件仅在其父级重新渲染或其 props 更改时才重新渲染。

使用这段代码观察到底发生了什么:

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>;
};

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

发生此行为是因为您将 用户计数作为可观察变量

根据 mobx-react 文档

Observer is a React component, which applies observer to an anonymous region in your component. It takes as children a single, argumentless function which should return exactly one React component. The rendering in the function will be tracked and automatically re-rendered when needed.

和 mobx 文档

When autorun is used, the provided function will always be triggered once immediately and then again each time one of its dependencies changes.

您可以通过直接在功能组件中登录来确认此行为,您将观察到该组件仅呈现一次

编辑:

回答你的问题

If I change useEffect to this

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

basically remove anonymous function from useEffect and just pass autorun directly, then it is run only once. Why is it so? What's the difference?

不同之处在于 autorun returns 一个 disposer function 当 运行 将处理掉 autorun 并且不再执行它。

来自文档:

The return value from autorun is a disposer function, which can be used to dispose of the autorun when you no longer need it.

现在发生的事情是,由于 useEffect 在 运行s 时执行提供给它的回调,执行的回调是 auto运行 返回的 disposer 函数,这实际上取消了你的自动运行.