SetIinterval/Polling every 5 seconds resets the values of my state variables/args instead of keeping the most recently set ones?

huangapple go评论92阅读模式
英文:

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

  1. const [responseData, setResponseData] = useState('')
  2. const [numericalArg, setNumericalArg] = useState('')
  3. /* or I have */:
  4. const numericalArg = useRef('')
  5. const handleTopRequest = (arg1) => {
  6. url = "base_url" + `?${numericalArg}`
  7. axios.get(url)
  8. .then(response => {
  9. setResponse(response)
  10. }
  11. }
  12. useEffect(() => {
  13. handleTopRequest(sortByParam);
  14. const intervalId = setInterval(handleTopRequest, 5000);
  15. return () => clearInterval(intervalId);
  16. }, []);
  17. const handleNumArgChange = (event) => {
  18. setNumericalArg(event.target.value);
  19. // numProcesses.current = event.target.value;
  20. };
  21. return
  22. <div>
  23. <label>
  24. Number of Processes:
  25. <input
  26. type="number"
  27. value={numericalArg}
  28. onChange={handleNumArgChange}/>
  29. </label>
  30. ...
  31. <div>{JSON.stringify(responseData)}</div>
  32. </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回调函数中访问引用的当前值。

示例:

  1. const [responseData, setResponseData] = useState('');
  2. const [numericalArg, setNumericalArg] = useState('');
  3. // 引用用于保存当前状态值
  4. const numericalArgRef = useRef(numericalArg);
  5. // 在更新时缓存当前状态值的效果
  6. useEffect(() => {
  7. numericalArgRef.current = numericalArg;
  8. }, [numericalArg]);
  9. useEffect(() => {
  10. const handleTopRequest = () => {
  11. // 访问当前 numericalArgRef 值
  12. url = "base_url" + `?${numericalArgRef.current}`;
  13. axios.get(url).then(setResponse);
  14. };
  15. handleTopRequest();
  16. const intervalId = setInterval(handleTopRequest, 5000);
  17. return () => clearInterval(intervalId);
  18. }, []);
  19. const handleNumArgChange = (event) => {
  20. setNumericalArg(event.target.value);
  21. };
  22. return (
  23. <div>
  24. <label>
  25. 进程数量
  26. <input
  27. type="number"
  28. value={numericalArg}
  29. onChange={handleNumArgChange}
  30. />
  31. </label>
  32. ...
  33. <div>{JSON.stringify(responseData)}</div>
  34. </div>
  35. );
英文:

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 &quot;&quot;, 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:

  1. const [responseData, setResponseData] = useState(&#39;&#39;);
  2. const [numericalArg, setNumericalArg] = useState(&#39;&#39;);
  3. // Ref to hold current state value
  4. const numericalArgRef = useRef(numericalArg);
  5. // Effect to cache current state value when it updates
  6. useEffect(() =&gt; {
  7. numericalArgRef.current = numericalArg;
  8. }, [numericalArg]);
  9. useEffect(() =&gt; {
  10. const handleTopRequest = () =&gt; {
  11. // Access current numericalArgRef value
  12. url = &quot;base_url&quot; + `?${numericalArgRef.current}`;
  13. axios.get(url).then(setResponse);
  14. };
  15. handleTopRequest();
  16. const intervalId = setInterval(handleTopRequest, 5000);
  17. return () =&gt; clearInterval(intervalId);
  18. }, []);
  19. const handleNumArgChange = (event) =&gt; {
  20. setNumericalArg(event.target.value);
  21. };
  22. return (
  23. &lt;div&gt;
  24. &lt;label&gt;
  25. Number of Processes:
  26. &lt;input
  27. type=&quot;number&quot;
  28. value={numericalArg}
  29. onChange={handleNumArgChange}
  30. /&gt;
  31. &lt;/label&gt;
  32. ...
  33. &lt;div&gt;{JSON.stringify(responseData)}&lt;/div&gt;
  34. &lt;/div&gt;
  35. );

huangapple
  • 本文由 发表于 2023年7月20日 10:26:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76726292.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定