Reputation: 147
I'm sending a request like this:
function getDecks() {
return Axious.get(urlGetAllDecks).then((response) => response.data);
}
I'm then using a functional component, where I try to initialize the state by calling the above function from my database.js file. However, the useEffect block is called countless times.
export interface DeckSelectionState {
id: number;
module: number;
title: string;
description: string;
dateCreated: string;
reviewStatus: number;
nextReviewDate: string;
}
const DeckSelection: React.FunctionComponent = () => {
const [decks, setDecks] = React.useState<DeckSelectionState[]>([]);
React.useEffect(() => {
database.getDecks().then((response) => {
setDecks(response);
});
});
Any idea on how to fix this?
Upvotes: 1
Views: 1018
Reputation: 1877
In order to make sure that the useEffect
is only executed once, you must specify an empty dependency list by passing an empty array.
The code should look like the following:
React.useEffect(() => {
database.getDecks().then((response) => {
setDecks(response);
});
}, []);
The second parameter of useEffect
is the dependencies array and it specifies the list of values that the effect depend on, which means that the effect will only be executed if one of those values change. By specifying the array []
you are basically saying that the effect does not depend on any value and should only be executed once, while not specifying the dependency array means that the effect depend on all props and state.
From the documentation:
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works. If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.
Why not specify [setDecks]
as the dependency array?
setDecks
is the function for setting the state corresponding to the useState hook you have used. While you can add it to the dependency array as the effect seems to "depend" on it, it will never change, thus it will never impact the effect.
From the documentation on useState
:
React guarantees that setState function identity is stable and won’t change on re-renders. This is why it’s safe to omit from the useEffect or useCallback dependency list.
Upvotes: 4