[英]How to handle case in React.js hooks when the previous state is in the closure of component's method?
I have a component which waits for an API call, sets an empty array as initial state and then on props change it sets the new array.我有一个等待 API 调用的组件,将一个空数组设置为初始状态,然后在道具更改时设置新数组。
const [options, setOptions] = useState([]);
useEffect(() => {
setOptions(optionsFromProps);
}, [optionsFromProps]);
The problem is, that I have a function inside of the component which has closure over the first empty array and when I call it, it's being called with empty array event though now options is [{}, {}, {}];问题是,我在组件内部有一个函数,它在第一个空数组上有闭包,当我调用它时,它被空数组事件调用,尽管现在选项是 [{}, {}, {}];
// inside of the same component
const foo = () => console.log(options);
// it logs []
// if the initial state would be [1,2,3] then it logs [1,2,3]
After an additional discussion over the problem with my colleague, he pointed out that I haven't understood the problem.在与我的同事进一步讨论这个问题后,他指出我没有理解这个问题。 Basically, the initial question is incorrect and the bug was because in the child component I attached an event listener which had closure over the initial state.
基本上,最初的问题是不正确的,错误是因为在子组件中,我附加了一个事件侦听器,该侦听器在初始状态上有闭包。
CodeSundbox example CodeSundbox 示例
So after this, the fix was obvious: on every rerender, the function should be updated, not only on the initial render.所以在这之后,修复是显而易见的:在每次重新渲染时,应该更新函数,而不仅仅是在初始渲染上。
import React, { useState, useEffect } from "react";
const Component = () => {
const [options, setOptions] = useState([]);
useEffect(() => {
const onMouseDown = () => {
foo();
};
document.addEventListener("mousedown", onMouseDown);
return () => document.removeEventListener("mousedown", onMouseDown);
}); // fixed
// }, []); with a bug
const foo = () => {
setOptions(options);
};
const handleClick = () => {
setOptions([1, 2, 3]);
};
return (
<div>
<button onClick={handleClick}>Click me!</button>
<ul>
{options.map(option => (
<li>{option}</li>
))}
</ul>
</div>
);
};
export default Component;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.