英文:
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>
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论