Реакция useEffect - почему свойство объекта замыкания не обновляется? - PullRequest
1 голос
/ 08 мая 2019

В приведенном ниже примере, почему функция выборки из 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 голосов
/ 08 мая 2019

Если при нажатии кнопки появляется «Не реализовано», это происходит потому, что 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

...