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

问题描述 投票:1回答:1

使用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()中的useEffect()回调中的MessagingComponent函数:

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

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

我怎么能避免这个?我应该简单地在useEffect()钩子中放入if条件,并检查messages属性吗?

reactjs redux react-hooks
1个回答
5
投票

如果我理解正确,你想通过useEffect()模仿基于常规类的反应组件的“on component mounted”行为,这样效果回调只会在第一次渲染时触发一次。

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

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

第二个数组参数允许您指定哪些prop变量在其值发生变化时触发userEffect()回调(如果有)。

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

有关第二个参数的更多信息,see this documentationthis documentation


0
投票

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

检查以下示例,

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

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

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

考虑我们将人员数组传递到功能组件的道具中,并且我们希望警报仅在人员阵列发生变化时执行。

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

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

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

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

你可以修改你的useEffect()钩子如下所示只调用一次来获取API数据,

useEffect(() => {
    loadMessages();
  }, []);
© www.soinside.com 2019 - 2024. All rights reserved.