Reputation: 93
I got a button that triggers data fetching from fetchDataHandler
, that works with useEffect
, it fetch data on page load also. But then when I add addMovieHandler
as dependency to useEffect
to auto-fetch data when I add another movie, it just doesn't work. So I figured out I may be using it wrong, but cant figure it out.
const App = () => {
const [movies, setMovies] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const fetchDataHandler = useCallback(async () => {
setIsLoading(true);
const respone = await fetch(
"https://react-http-3af47-default-rtdb.firebaseio.com/movies.json"
);
if (!respone.ok) {
setIsLoading(false);
throw new Error("Something went wrong!");
}
const data = await respone.json();
const movieList = [];
for (const key in data) {
movieList.push({
id: key,
title: data[key].title,
text: data[key].text,
});
}
setMovies(movieList);
setIsLoading(false);
}, []);
const addMovieHandler = useCallback(async (movie) => {
const respone = await fetch(
"https://react-http-3af47-default-rtdb.firebaseio.com/movies.json",
{
method: "POST",
body: JSON.stringify(movie),
headers: {
"Content-Type": "application/json",
},
}
);
const data = await respone.json();
console.log(data);
}, []);
useEffect(() => {
fetchDataHandler();
}, [fetchDataHandler, addMovieHandler]);
let content = <p>no movies found</p>;
if (movies.length > 0) {
content = <MovieList movies={movies} />;
}
if (isLoading) {
content = <p>loading...</p>;
}
return (
<React.Fragment>
<UserInput onAddMovie={addMovieHandler}></UserInput>
<Card>
<button onClick={fetchDataHandler}>Fetch movies</button>
</Card>
{content}
</React.Fragment>
);
};
export default App;
Upvotes: 1
Views: 858
Reputation: 5715
Your useEffect
is not triggering on addMovieHandler
reference change because you're using useCallback
with no dependencies ([]
second parameter) to memoize it. This means the addMovieHandler
reference won't change at all between rerenders but you're basing your useEffect
calls on it doing so. In simple words - useEffect
won't rerun if the provided dependencies have the same values (which is the case in your solution).
Same goes for fetchDataHandler
.
In any case, this is not a good solution to the problem. You should be better-off updating your movies
array on successful movie addition in the addMovieHandler
itself. Same goes for other operations like delete and update.
Upvotes: 1
Reputation: 111
Try this instead:
Remove addMovieHandler
from useEffect
. When you hit addMovieHandler
it is fetching the data anyway. So what you could to is set the movies with the latest response in the handler itself like so:
setMovies(...data)
This will replace the movie list with the newly fetched movie list. If you want to add on the old list you could do this:
setMovies([...movies, data])
This is concatenate the new fetched list to the already existing movie list and update the variable and re-render the movie list section as well.
Upvotes: 1