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

时间:2019-04-02 21:47:29

标签: reactjs redux react-hooks

使用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);

如您所见,我有一个效果回调,它在loadMessages()的{​​{1}}回调中调用useEffect()函数:

MessagingComponent

useEffect(() => { loadMessages(); }); 的调用会加载消息,从而导致组件重新呈现。此行为是预期的,但是问题在于重新渲染会导致loadMessages()挂钩再次触发,从而导致useEffect()被再次调用。反过来,这会从后端加载消息,并使组件再次呈现,并且循环重复进行。

如何避免这种情况?我是否应该在loadMessages()挂钩中放入if条件,并检查messages属性?

2 个答案:

答案 0 :(得分:2)

如果我的理解正确,您想通过useEffect()模仿基于常规类的常规组件的“在组件上安装”的行为,以使效果回调仅在第一个渲染上触发一次。

要实现该行为,可以将空数组传递给useEffect()的第二个参数,如下所示:

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

第二个数组参数允许您指定当变量的值更改时,哪些prop变量会触发userEffect()回调(如果有)。

通过传递一个空数组,这意味着useEffect()不会被输入prop输入变量的任何更改所触发,并且在第一个渲染期间只会被调用一次。 >

有关第二个参数see this documentationthis documentation

的更多信息

答案 1 :(得分:0)

useEffect()是功能组件的反应挂钩,涵盖了类组件的生命周期挂钩的功能。 useEffect()组合了类组件的componentDidMount(), componentDidUpdate()componentWillUnmount(),这意味着它将在安装组件时,组件状态改变时以及从DOM卸载组件时执行。

检查以下示例,

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

当组件被安装/初始渲染,组件的状态改变以及从DOM卸载组件时,将执行以上代码/警告。

为使上述代码运行更少,我们可以将值的数组作为第二个参数传递,作为该效果的依赖项。如果其中一项依赖项发生更改,效果将再次运行。

考虑到我们将人员数组传递到功能组件的props中,我们希望仅在人员数组更改时执行警报。

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

这将在初始渲染期间和props.persons更改时执行代码。

因此,仅在初始渲染/组件安装期间执行代码,您可以传递一个空数组,这意味着在效果应执行时未指定任何依赖项。因此,在初始渲染期间和卸载组件时运行。

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

您可以按如下所示修改useEffect()钩子,使其仅调用一次即可获取API数据,

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