Reputation: 1551
I'm trying to handle an async function to insert data in a database. Unfortunately the eslint react-hooks/exhaustive-deps
requires me to add my score
state in the useCallback
. Although when I add this my app get in an infinite loop state.
When I add eslint-disable-line
on the callback requirements line my code runs perfectly fine. Why is this rule in there, and how to solve it the correct way without disabling the eslint rule?
import React, { useState, useEffect, useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { insertData } from 'ducks/data';
const App = () => {
const dispatch = useDispatch();
const sliderData = useSelector((state) => state.data.sliders);
const [score, setScore] = useState(0);
const handleData = useCallback(() => {
dispatch(insertData(score));
}, [dispatch]); // eslint-disable-line
useEffect(() => {
for (const [key, value] of Object.entries(sliderData)) {
const sliders = Object.values(value);
const totalSliderScore = sliders.reduce((a, b) => a + b, 0);
setScore((prevScore) => prevScore += totalSliderScore);
// Last slider in array
if (key === 'lastKey') {
handleData();
}
}
}, [sliderData, handleData]);
return ...
};
export default App;
Upvotes: 0
Views: 621
Reputation: 172
any state variable used in a useCallback
should be included in the dependency list otherwise you might get stale data of that variable.
const handleData = useCallback(() => {
dispatch(insertData(score));
}, [dispatch, score]);
and why do you need the function handleData
in the dependency list of useEffect
? Isn't that causing the loop. I think also changing to the following should solve the infinite loop.
useEffect(() => {
for (const [key, value] of Object.entries(sliderData)) {
const sliders = Object.values(value);
const totalSliderScore = sliders.reduce((a, b) => a + b, 0);
setScore((prevScore) => prevScore += totalSliderScore);
// Last slider in array
if (key === 'lastKey') {
handleData();
}
}
}, [sliderData]);
Upvotes: 0
Reputation: 181
You can create a reference of the latest score so that it will not cause the loop
const [score, setScore] = useState(0);
const latestScore = useRef();
const handleData = useCallback(() => {
dispatch(insertData(latestScore));
}, [dispatch,latestScore]); // eslint-disable-line
useEffect(() => {
...
latestScore.current = score
}
}, []);
Upvotes: 1