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

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

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 &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:

const [responseData, setResponseData] = useState(&#39;&#39;);
const [numericalArg, setNumericalArg] = useState(&#39;&#39;);

// Ref to hold current state value
const numericalArgRef = useRef(numericalArg);

// Effect to cache current state value when it updates
useEffect(() =&gt; {
  numericalArgRef.current = numericalArg;
}, [numericalArg]);

useEffect(() =&gt; {
  const handleTopRequest = () =&gt; {
    // Access current numericalArgRef value
    url = &quot;base_url&quot; + `?${numericalArgRef.current}`;

    axios.get(url).then(setResponse);
  };

  handleTopRequest();

  const intervalId = setInterval(handleTopRequest, 5000);
  return () =&gt; clearInterval(intervalId);
}, []);

const handleNumArgChange = (event) =&gt; {
  setNumericalArg(event.target.value);
};

return (
  &lt;div&gt;
    &lt;label&gt;
      Number of Processes:
      &lt;input
        type=&quot;number&quot;
        value={numericalArg}
        onChange={handleNumArgChange}
      /&gt;
    &lt;/label&gt;
    ...
    &lt;div&gt;{JSON.stringify(responseData)}&lt;/div&gt;
  &lt;/div&gt;
);

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:

确定