Redux:为什么我的 useEffect() 会在每个页面重新渲染时不断重新渲染它的值

Redux: Why does my useEffect() keeps rerendering its value on every page rerender

我在学习react-redux。 我遇到了以下问题:

  1. 我进行了两次异步 api 调用(使用 redux-thunk):
  1. 我之后使用的那些国家/地区名称进行第二次 api 调用,以获取这些国家/地区的所有足球联赛(有时,有 none,所以我得到一个 null).在这种情况下,将分别使用每个 countryName 进行调用。我从结果中得出一个数组。
  2. 这个数组长度为 255 米,我从中过滤掉 null 值并映射联赛名称。
  3. 点击联赛名称后,会呈现一个页面 ({Link} from "react-router-dom";)。 现在我的问题出现了
  4. 当我单击以返回我的主页 (<Link to={"/"} >) 时,两个 useEffect() 正在再次进行 api 呼叫。为什么?

这是我的 useEffect():

的代码
const dispatch = useDispatch();
const selectAllCountries = useSelector(state => state.allCountries);
const selectAllLeagues = useSelector(state => state.allLeagues);

useEffect(() => {
    dispatch(allCountries());
}, [dispatch]);

useEffect(() => {
    if(!_.isEmpty(selectAllCountries.data)) {
        selectAllCountries.data.countries.map(el => dispatch(allLeagues(el.name_en)));
    }
}, [dispatch, selectAllCountries.data]);

我尝试制作一个自定义挂钩并将 useEffect() 放在那里:

const useCountries = getCountries => {useEffect(() => {
dispatch(getCountries());
},[getCountries])}

useCountries(allCountries);

按照此处的建议:

但这并没有帮助。

如有任何帮助,我们将不胜感激。


答案:

在“./actions/.../allLeagues.js

...
import _ from "lodash";

export const allLeagues = (country) => async (dispatch, getState) => {

    if (!_.isEmpty(getState().allLeagues) && !_.isEmpty(getState().allLeagues.data)) {
        return Promise.resolve();
    } else {
        try {

          ...
        
        }
    }    
}

问题,这也很有帮助: Fetching data from store if exists or call API otherwise in React (看看关于 getStore() 的回答)

如上面的评论所述,当您单击转到新页面时,主页会卸载。当您返回时,页面 re-mounts 和效果再次运行,触发另一个 API 调用。您可以通过检查这些值是否已存在于您的商店中来阻止 API 调用。我个人喜欢在 action creator 中这样做,但您也可以在 effect 中这样做。

检查动作创建器中的状态:

function allLeagues(countryName) {
  return (dispatch, getState) => {
    // Call `getState` and check whether `allLeagues` has been populated yet.
    const { allLeagues } = getState();

    if (allLeagues && allLeagues.data && allLeagues.data.length) {
      // You already have the data, no need to make the API call.
      return Promise.resolve();
    }

    // No data, make the API call...
  };
}

正在检查效果中的状态:

useEffect(() => {
  // Check whether the league data is set or not.
  if(!_.isEmpty(selectAllCountries.data) && _.isEmpty(selectAllLeagues.data)) {
    selectAllCountries.data.countries.map(el => dispatch(allLeagues(el.name_en)));
  }
}, [dispatch, selectAllCountries.data, selectAllLeagues.data]);