Redux:为什么我的useEffect()会在每次重新呈现页面时不断重新呈现其值

时间:2020-10-06 20:28:13

标签: reactjs redux react-redux react-router-dom redux-thunk

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

  1. 我进行了两个异步api调用(使用redux-thunk):
  • 第一个获取国家名称的人(在一个对象中,例如:{countries: [{...}, ...]}
  1. 此后,我使用这些国家/地区名称进行第二次api调用,以获取该国家/地区中的所有足球联赛(有时没有,因此我得到了null)。在这种情况下,将分别与每个countryName进行呼叫。我从结果中组成一个数组。
  2. 此数组的长度为255m,我从中过滤出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);

如此处建议: React hooks: dispatch action from useEffect

但这没有帮助。

将为您提供任何帮助。


答案:

在“ ./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()的答案)

1 个答案:

答案 0 :(得分:2)

如上面的评论中所述,当您单击以转到新页面时,主页将卸载。当您返回时,页面将重新安装,并且效果再次运行,从而触发另一个API调用。您可以通过检查商店中是否已经存在值来阻止API调用。我个人喜欢在动作创建者中执行此操作,但是您也可以在效果上执行此操作。

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

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]);