web-dev-qa-db-ja.com

Reactフックは、関数コンポーネントの本体内でのみ呼び出すことができます

コンポーネントのレンダリングではなく、ボタンのクリックでuseEffect()をトリガーするにはどうすればよいですか?

このような関数内で使用すると、次のエラーが表示されます。

フックは関数コンポーネントの本体内でのみ呼び出すことができます

function App() {

  function buttonClicked() {  
    useEffect(() => {
      // Fetch from API
    });
  }

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1 className="App-title">App Title</h1>
      </header>
      <p className="App-intro">
        To get started, edit <code>src/App.js</code> and save to reload.
      </p>
      <button onClick={buttonClicked}>Make API Call</button>
    </div>
  );
}
4
Alan

useEffectの使い方を誤解しているようですね。これはcomponentDidUpdateフックに似ています-いくつかの関数によって直接ではなく、値の変更に応じてトリガーされます。 renderメソッドが呼び出されると、useEffectも呼び出されます。何が目的かはわかりませんが、スニペットからはフックなしでfetchを呼び出すだけが最も理にかなっています。しかし、あなたの質問に答えるために、useEffectをトリガーする1つの方法は、状態を更新することです。特定のプロパティの値が変更された場合にのみトリガーされるuseEffectフックを作成できます。

const [buttonClicked, setButtonClicked] = useState(false);

useEffect(() => {
  // Fetch from API
}, [buttonClicked]); 

<button onClick={() => setButtonClicked(true)}>Make API Call</button>

これでクリックするとuseEffectがトリガーされますが、, [buttonClicked]を追加したため、他のプロパティ値が変更されても呼び出されません。

受け入れられた答えは、正確なIMOではありません。ボタンをクリックしたときにデータフェッチをトリガーすることが目的の場合、useEffectは必要ありません。 useEffectは、ライフサイクルフック-componentDidMountcomponentDidUpdate、およびcomponentWillUnmountを置き換えるために使用されます。

これについて考えてください-フックなしで、あなたが望むものを達成するためにこれらのライフサイクルフックが必要ですか?クラスでは、this.stateと、ボタンをクリックしたときにトリガーされるコールバックを使用するだけです。これらのライフサイクルフックは使用しません。

実現したい副作用はデータのフェッチですが、これはユーザーがトリガーする効果であり、useEffectはここでは役に立ちません。 useEffectは、コンポーネントのライフサイクル中に副作用が発生する場合にのみ役立ちます。

以下のコードは、フックで実現したいことを実行する必要があります。useEffectは不要で、useStateのみが必要です。

function App() {
  const [user, setUser] = React.useState(null);

  function fetchData() {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        setUser(data.results[0]);
      });
  };
  
  return <div>
    <p>{user ? user.name.first : 'No data'}</p>
    <button onClick={fetchData}>Fetch Data</button>
  </div>;
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

<div id="app"></div>
10
Yangshun Tay