React Hooks 只能在函数组件内部调用

React Hooks can only be called inside the body of a function component

如何在单击按钮而不是渲染组件时触发 useEffect()

当我在这样的函数中使用它时,我收到一条错误消息:

Hooks can only be called inside the body of a function component

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

听起来你误解了 useEffect 的用法。就像 componentDidUpdate 钩子 - 它是根据值的变化触发的,而不是直接由某个函数触发的。当调用render方法时,也会调用useEffect。很难说出你的目标是什么,但从你的代码片段来看,最有意义的是不带任何钩子地调用 fetch 。但是要回答你的问题,触发 useEffect 的一种方法是更新你的状态,你可以创建 useEffect 挂钩,只有当特定 属性 的值发生变化时才会触发:

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

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

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

现在当你点击时,useEffect应该被触发,但是因为你添加了, [buttonClicked],如果任何其他属性值改变,它不会被调用。

如果您的目标是在单击按钮时触发数据获取,则不需要 useEffectuseEffect 用于替换生命周期挂钩 - componentDidMountcomponentDidUpdatecomponentWillUnmount.

想一想 - 如果没有钩子,你是否需要这些生命周期钩子来实现你想要的?使用 类,您只需使用 this.state 和点击按钮时触发的回调;您不会使用这些生命周期挂钩中的任何一个。

您想要实现的副作用是数据获取,但这是用户触发的效果,useEffect 在这里没有帮助。 useEffect 仅当您希望在组件的生命周期中产生副作用时才有用。

下面的代码应该可以实现你想用hooks实现的功能,不需要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/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>