React useEffect - 为什么闭包对象中的 属性 没有更新?

React useEffect - Why property from closure object does't get updated?

在下面的示例中,为什么从 obj 获取的函数没有更新我在 useEffect 中设置的新函数?

import React, {useEffect} from 'react';

function Example () {
  const obj = {
    fetch: () => {
      throw 'Not implemented!';
    }
  }

  useEffect(() => {
    obj.fetch = async () => {
      const data = await fetch('https://my.url.com');
      console.log('Data:', data);
    };

    obj.fetch();
  }, []);

  return (
    // the button click is throwing "Not implemented"
    <button onClick={() => obj.fetch()}>Test</button>
  );
}

如果按钮点击抛出 "Not implemented",这是因为 Example 在按钮点击之前 re-rendered。如果您使用下面我的代码的沙箱,您会发现只要您不单击 "Trigger render","Test" 按钮就会按预期工作。您的 useEffect 依赖项数组仅设置为在挂载时执行。 re-render 创建一个新的 obj,它永远不会重新分配 fetch 函数。

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

function Example() {
  const obj = {
    fetch: () => {
      console.error("Not implemented!");
    }
  };

  useEffect(() => {
    obj.fetch = async () => {
      console.log("Implemented");
    };

    obj.fetch();
  }, []);

  return (
    <button onClick={() => obj.fetch()}>Test</button>
  );
}

function App() {
  const [renderTrigger, setRenderTrigger] = useState(0);
  return (
    <>
      <Example />
      <br />
      <button onClick={() => setRenderTrigger(prev => prev + 1)}>
        Trigger render
      </button>
      <br />
      {renderTrigger}
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);