我正在学习react-redux
。
我遇到以下问题:
redux-thunk
):{countries: [{...}, ...]}
。null
)。在这种情况下,将分别与每个countryName进行呼叫。我从结果中组成一个数组。null
值并映射联赛名称。{Link} from "react-router-dom";
)。
现在我的问题发生了 <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()
的答案)
答案 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]);