Reputation: 384
I am learning react-redux
.
I got the following problem:
redux-thunk
):{countries: [{...}, ...]}
.null
). In this case, the call is made with each countryName separatly. I make out of the results an array.null
values and map the leagues names.{Link} from "react-router-dom";
).
NOW my problem occurs<Link to={"/"} >
), both useEffect()
are making an api call again. Why?Here is the code for my 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]);
I tried to make a custom hook and put the useEffect()
in there:
const useCountries = getCountries => {useEffect(() => {
dispatch(getCountries());
},[getCountries])}
useCountries(allCountries);
as suggested here: React hooks: dispatch action from useEffect
But it didnt help.
Will be greatful for any help.
ANSWER:
in "./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 {
...
}
}
}
Question, that was also helpfull:
Fetching data from store if exists or call API otherwise in React
(take look at answer about getStore()
)
Upvotes: 0
Views: 554
Reputation: 3499
As mentioned in a comment above, the homepage unmounts when you click to go to a new page. When you go back, the page re-mounts and the effect runs again, triggering another API call. You can prevent the API call by checking whether or not the values already exist in your store. I personally like to do this in the action creator, but you could do it in the effect as well.
Checking state in the action creator:
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...
};
}
Checking state in the effect:
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]);
Upvotes: 2