假设我们有一个组件Accordion,它有一个内部状态isOpen,因此您可以关闭和打开这个组件。
现在我们想要一个父组件,它也有一个状态isOpen,并且有一个按钮。在这个组件中,我们有2个Accordion并将isOpen传递给Accordion,如果父组件改变状态isOpen,则希望Accordion接受这一变化。
所有组件都是函数组件。
在这种情况下,Accordion在第一次渲染时将作为初始状态的父isOpen属性。如果我们按下按钮切换isOpen parent,我们将更改父状态但子项将不会更新。
为了解决这个问题,我们可以使用useEffect。
在这种情况下,当父组件改变isOpen状态时,子组件将被正确更新。
但是有一个问题:
“React Hook useEffect has a missing dependency: 'isOpen'. Either include it or remove the dependency array react-hooks/exhaustive-deps”
那么如何消除esLint报告的这个问题呢?我们不想将isOpen放入依赖数组中,因为这会导致错误。
如果我们像这样将isOpen添加到数组中:
我们会有这样一种情况,当我们点击手风琴(accordion)中的内部按钮并更新内部状态时,useEffect将运行并发现父组件与子组件具有不同的状态,然后立即设置旧状态。
因此,实际上你会进入一个循环,手风琴将永远不会打开。
问题是基于父组件的状态,如何最好地更新子组件的状态?
请不要建议将所有状态都放在父组件中并传递不带子状态的 props。由于此示例中的两个手风琴必须拥有自己的状态并能够以独立的方式打开和关闭,但如果父组件说关闭或打开,它应该听取。
谢谢!
现在我们想要一个父组件,它也有一个状态isOpen,并且有一个按钮。在这个组件中,我们有2个Accordion并将isOpen传递给Accordion,如果父组件改变状态isOpen,则希望Accordion接受这一变化。
所有组件都是函数组件。
const Accordion = ({ isOpen: parentIsOpen = false }) => {
const [isOpen, setIsOpen] = useState(parentIsOpen);
const handleSetIsOpen = () => setIsOpen(!isOpen);
return (
<div>
I'm open: {isOpen}
<button onClick={handleSetIsOpen}>toggle isOpen child</button>
</div>
);
};
const MasterComponent = () => {
const [isOpen, setIsOpen] = useState(false);
const handleSetIsOpen = () => setIsOpen(!isOpen);
return (
<div>
<button onClick={handleSetIsOpen}>toggle isOpen parent</button>
<Accordion isOpen={isOpen} />
<Accordion isOpen={isOpen} />
</div>
);
};
在这种情况下,Accordion在第一次渲染时将作为初始状态的父isOpen属性。如果我们按下按钮切换isOpen parent,我们将更改父状态但子项将不会更新。
为了解决这个问题,我们可以使用useEffect。
const Accordion = ({ isOpen: parentIsOpen = false }) => {
const [isOpen, setIsOpen] = useState(parentIsOpen);
const handleSetIsOpen = () => setIsOpen(!isOpen);
useEffect(() => {
if (parentIsOpen !== isOpen) {
setIsOpen(parentIsOpen);
}
}, [parentIsOpen]);
return (
<div>
I'm open: {isOpen}
<button onClick={handleSetIsOpen}>toggle isOpen child</button>
</div>
);
};
const MasterComponent = () => {
const [isOpen, setIsOpen] = useState(false);
const handleSetIsOpen = () => setIsOpen(!isOpen);
return (
<div>
<button onClick={handleSetIsOpen}>toggle isOpen parent</button>
<Accordion isOpen={isOpen} />
<Accordion isOpen={isOpen} />
</div>
);
};
在这种情况下,当父组件改变isOpen状态时,子组件将被正确更新。
但是有一个问题:
“React Hook useEffect has a missing dependency: 'isOpen'. Either include it or remove the dependency array react-hooks/exhaustive-deps”
那么如何消除esLint报告的这个问题呢?我们不想将isOpen放入依赖数组中,因为这会导致错误。
如果我们像这样将isOpen添加到数组中:
useEffect(() => {
if (parentIsOpen !== isOpen) {
setIsOpen(parentIsOpen);
}
}, [parentIsOpen, isOpen]);
我们会有这样一种情况,当我们点击手风琴(accordion)中的内部按钮并更新内部状态时,useEffect将运行并发现父组件与子组件具有不同的状态,然后立即设置旧状态。
因此,实际上你会进入一个循环,手风琴将永远不会打开。
问题是基于父组件的状态,如何最好地更新子组件的状态?
请不要建议将所有状态都放在父组件中并传递不带子状态的 props。由于此示例中的两个手风琴必须拥有自己的状态并能够以独立的方式打开和关闭,但如果父组件说关闭或打开,它应该听取。
谢谢!