简体   繁体   English

ReactJS:如何只调用一次 useEffect 钩子来获取 API 数据

[英]ReactJS: how to call useEffect hook only once to fetch API data

Using React, I have the following functional component where I make use of useEffect() :使用 React,我有以下使用useEffect()功能组件:

import React, { useEffect } from 'react';
import { connect } from 'react-redux';

const MessagingComponent = React.memo(({ loadMessages, messages, ...props }) => {

  useEffect(() => {
    loadMessages();
  });

  return <div {...props}>These are the messages</div>;
});

const mapDispatchToProps = dispatch => ({
  loadMessages: () => dispatch({ type: 'LOAD_MESSAGES' })
});

const mapStateToProps = state => {
  return {
    messages: state.chatt.messages.chatMessages
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MessagingComponent);

As you can see, I have an effect callback that calls the loadMessages() function in the useEffect() callback in my MessagingComponent :如您所见,我有一个效果回调,它在我的MessagingComponentuseEffect()回调中调用loadMessages()函数:

  useEffect(() => {
    loadMessages();
  });

The call to loadMessages() loads messages which causes the component to re-render.loadMessages()的调用会加载导致组件重新渲染的消息。 This behaviour is as expected, however the problem is that the re-render causes the useEffect() hook to fire again, which causes loadMessages() to be called again.此行为符合预期,但问题在于重新渲染会导致useEffect()钩子再次触发,从而导致再次调用loadMessages() This in turn loads the messages from the back-end and causes the component to render again, and the cycle repeats.这反过来从后端加载消息并导致组件再次呈现,并且循环重复。

How can I avoid this?我怎样才能避免这种情况? Should I simply put an if condition in the useEffect() hook, and check for the messages property?我应该简单地在useEffect()钩子中放置一个 if 条件,并检查消息属性吗?

If I understand correctly, you want to mimic the "on component mounted" behaviour of regular class based react components via useEffect() , so that the effect callback only fires once on the first render.如果我理解正确,您想通过useEffect()模仿基于常规类的反应组件的“在组件上安装”行为,以便效果回调仅在第一次渲染时触发一次。

To achieve that behaviour, you can pass an empty array to the second argument of useEffect() like so:要实现该行为,您可以将一个空数组传递给useEffect()的第二个参数, useEffect()所示:

useEffect(() => {
  loadMessages();
}, []); /* <-- add this */

The second array argument allows you to specify which prop variables trigger the useEffect() callback (if any) when their value(s) change.第二个数组参数允许您指定哪些prop变量在其值更改时触发useEffect()回调(如果有)。

By passing an empty array, this means that useEffect() won't be triggered by any changes to input prop variables and will in turn only ever be called once, during the first render.通过传递一个空数组,这意味着useEffect()不会被输入prop变量的任何更改触发,并且只会在第一次渲染期间被调用一次。

For more information on this second argument, see this documentation and this documentation有关第二个参数的更多信息, 请参阅此文档此文档

useEffect() is a react hook for functional components which covers the functionality of the lifecycle hooks of the class components. useEffect()是功能组件的反应钩子,它涵盖了类组件的生命周期钩子的功能。 useEffect() combines componentDidMount(), componentDidUpdate() and componentWillUnmount() of the class components, which means it will execute when the component is mounted, when the state of the component changes and when the component is unmounted from the DOM. useEffect()结合了类componentDidMount(), componentDidUpdate()componentWillUnmount() ,这意味着它会在组件挂载、组件状态改变以及组件从 DOM 中卸载时执行。

Check below example,检查下面的例子,

useEffect(() => {
   setTimeout(() => {
      alert("data saved");
    }, 1000);
});

Above code/alert is executed when the component is mounted/initial render, when state of the component changes and when component is unmounted from the DOM.当组件安装/初始渲染、组件状态改变以及组件从 DOM 中卸载时,将执行上述代码/警报。

To make the above code run less often we can pass an array of values as the second argument, as the dependencies for that effect.为了减少上面的代码运行的频率,我们可以传递一个值数组作为第二个参数,作为该效果的依赖项。 If one of the dependencies change the effect will run again.如果依赖项之一发生变化,效果将再次运行。

Consider we have persons array passed into the props of the functional component and we want the alert to execute only when the persons array change.考虑我们将 people 数组传递到功能组件的 props 中,并且我们希望警报仅在 people 数组更改时执行。

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, [props.persons]);

This will execute the code during initial render and when props.persons changes.这将在初始渲染期间和props.persons更改时执行代码。

So to execute the code only during initial render/component mount you can pass an empty array which means no dependencies specified when the effect should execute.因此,要仅在初始渲染/组件挂载期间执行代码,您可以传递一个空数组,这意味着在执行效果时没有指定依赖项。 Hence run during initial render and when the component is unmounted.因此在初始渲染和卸载组件时运行。

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, []);

You can modify your useEffect() hook as below to call it only once to fetch API data,你可以修改你的useEffect()钩子,如下所示,只调用一次来获取 API 数据,

useEffect(() => {
    loadMessages();
  }, []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM