5

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

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

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

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

2 回答 2

11

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

想一想——如果没有钩子,你会需要这些生命周期钩子来实现你想要的吗?使用类,您只需要使用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/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>

于 2018-11-11T21:22:40.850 回答
3

听起来你误解了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],所以如果任何其他属性值发生变化,它就不会被调用。

于 2018-11-11T15:47:12.100 回答