英文:
SetIinterval/Polling every 5 seconds resets the values of my state variables/args instead of keeping the most recently set ones?
问题
在我的主要React组件中,我正在进行GET请求的地方,我有一个输入字段,可以将numericalArg设置为任何整数(如59)。然而,当定时器触发时,numericalArg被重置为基本上什么都没有,而不是理想值59。
我该如何修复这个问题?我尝试使用useRef(),它有点起作用(?),但它一点都不一致,甚至经常破坏输入字段(例如,我无法在numericalArg的输入字段中输入任何数字,原因不明)。
有什么帮助吗?
英文:
So in my primary React component where I'm making a GET request, I have
const [responseData, setResponseData] = useState('')
const [numericalArg, setNumericalArg] = useState('')
/* or I have */:
const numericalArg = useRef('')
const handleTopRequest = (arg1) => {
url = "base_url" + `?${numericalArg}`
axios.get(url)
.then(response => {
setResponse(response)
}
}
useEffect(() => {
handleTopRequest(sortByParam);
const intervalId = setInterval(handleTopRequest, 5000);
return () => clearInterval(intervalId);
}, []);
const handleNumArgChange = (event) => {
setNumericalArg(event.target.value);
// numProcesses.current = event.target.value;
};
return
<div>
<label>
Number of Processes:
<input
type="number"
value={numericalArg}
onChange={handleNumArgChange}/>
</label>
...
<div>{JSON.stringify(responseData)}</div>
</div>
I have an input field where I can set numericalArg to whatever integer I'd like (like 59). However, when the interval fires, numericalArg gets reset to essentially nothing, instead of the ideal value of 59.
How do I fix this? I tried using useRef(), and it kinda works (?), but it's not consistent at all and even breaks the input field many times (for example, I can't even type in any numbers in the input field for numericalArg for some reason).
Any help?
答案1
得分: 1
问题
问题在于handleTopRequest处理程序中对numericalArg状态值的闭包已经过时。useEffect钩子在组件挂载后运行一次,对初始的numericalArg值进行了闭包,即"",并实例化了间隔。间隔每次都调用相同的handleTopRequest回调的这个实例。
解决方案
我认为您正在尝试使用React引用是正确的方法。使用React引用和useEffect钩子来缓存当前状态值,并在handleTopRequest回调函数中访问引用的当前值。
示例:
const [responseData, setResponseData] = useState('');
const [numericalArg, setNumericalArg] = useState('');
// 引用用于保存当前状态值
const numericalArgRef = useRef(numericalArg);
// 在更新时缓存当前状态值的效果
useEffect(() => {
numericalArgRef.current = numericalArg;
}, [numericalArg]);
useEffect(() => {
const handleTopRequest = () => {
// 访问当前 numericalArgRef 值
url = "base_url" + `?${numericalArgRef.current}`;
axios.get(url).then(setResponse);
};
handleTopRequest();
const intervalId = setInterval(handleTopRequest, 5000);
return () => clearInterval(intervalId);
}, []);
const handleNumArgChange = (event) => {
setNumericalArg(event.target.value);
};
return (
<div>
<label>
进程数量:
<input
type="number"
value={numericalArg}
onChange={handleNumArgChange}
/>
</label>
...
<div>{JSON.stringify(responseData)}</div>
</div>
);
英文:
Issue
The issue here is a stale closure over the numericalArg state value in the handleTopRequest handler. The useEffect hook runs once after the component mounts, closes over the initial numericalArg value, i.e "", and instantiates the interval. The interval calls this same instance of the handleTopRequest callback each time.
Solution
I think you are on the right track trying to use a React ref. Use a React ref and a useEffect hook to cache the current state value, and access the ref's current value in the handleTopRequest callback function.
Example:
const [responseData, setResponseData] = useState('');
const [numericalArg, setNumericalArg] = useState('');
// Ref to hold current state value
const numericalArgRef = useRef(numericalArg);
// Effect to cache current state value when it updates
useEffect(() => {
numericalArgRef.current = numericalArg;
}, [numericalArg]);
useEffect(() => {
const handleTopRequest = () => {
// Access current numericalArgRef value
url = "base_url" + `?${numericalArgRef.current}`;
axios.get(url).then(setResponse);
};
handleTopRequest();
const intervalId = setInterval(handleTopRequest, 5000);
return () => clearInterval(intervalId);
}, []);
const handleNumArgChange = (event) => {
setNumericalArg(event.target.value);
};
return (
<div>
<label>
Number of Processes:
<input
type="number"
value={numericalArg}
onChange={handleNumArgChange}
/>
</label>
...
<div>{JSON.stringify(responseData)}</div>
</div>
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论