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

时间:2019-05-08 18:32:20

标签: reactjs react-hooks

在下面的示例中,为什么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>
  );
}

1 个答案:

答案 0 :(得分:0)

如果按钮单击抛出“未实现”,那是因为在按钮单击之前重新渲染了Example。如果您在下面使用我的代码的沙盒,您会发现只要不单击“触发器渲染”,“测试”按钮就会按预期工作。您的useEffect依赖项数组仅设置为在安装时执行。重新渲染会创建一个新的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);

Edit useEffect