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

tmp*_*dev 6 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);
Run Code Online (Sandbox Code Playgroud)

如您所见,我有一个效果回调,loadMessages()useEffect()回调在my 的回调中调用该函数MessagingComponent

  useEffect(() => {
    loadMessages();
  });
Run Code Online (Sandbox Code Playgroud)

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

如何避免这种情况?我是否应该简单地将if条件放在useEffect()钩子中,并检查messages属性?

Dac*_*nny 10

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

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

useEffect(() => {
  loadMessages();
}, []); /* <-- add this */
Run Code Online (Sandbox Code Playgroud)

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

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

有关第二个参数的更多信息,请参阅本文档本文档。

  • 这会导致警告:`React Hook useEffect缺少依赖项:loadMessages包括它们或删除依赖项数组react-hooks / exhaustive-deps` (9认同)

Het*_*chh 6

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

检查下面的例子,

useEffect(() => {
   setTimeout(() => {
      alert("data saved");
    }, 1000);
});
Run Code Online (Sandbox Code Playgroud)

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

为了减少上面的代码运行的频率,我们可以传递一个值数组作为第二个参数,作为该效果的依赖项。如果依赖项之一发生变化,效果将再次运行。

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

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

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

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

useEffect(() => {
    setTimeout(() => {
      alert("data saved");
    }, 1000);
  }, []);
Run Code Online (Sandbox Code Playgroud)

您可以useEffect()按如下方式修改您的钩子以仅调用一次以获取 API 数据,

useEffect(() => {
    loadMessages();
  }, []);
Run Code Online (Sandbox Code Playgroud)