这是您描述的两种情况(父>子和子>父)的一个非常基本的示例。父母持有状态,有一些修改它的功能,并呈现两个孩子。
https://codesandbox.io/s/silly-browser-y9hdt?file=/src/App.tsx
const Parent = () => {
const [counter, setCounter] = useState<number>(1);
const handleIncrement = () => {
setCounter((prevCount) => prevCount + 1);
};
const handleDecrement = () => {
setCounter((prevCount) => prevCount - 1);
};
// used as prop with the children
const doubleTheCounter = () => {
setCounter((prevCount) => prevCount * 2);
};
return (
<div>
<h1>Parent counter</h1>
<p>{counter}</p>
<button onClick={handleIncrement}>+</button>
<button onClick={handleDecrement}>-</button>
<ChildTriple countFromParent={counter} />
<DoubleForParent doubleCallback={doubleTheCounter} />
</div>
);
};
第一个子节点从父节点接收状态并使用显示不同的东西(在本例中为“三重”):
type ChildTripleProps = { countFromParent: number };
// Receives count state as prop
const ChildTriple = ({ countFromParent }: ChildTripleProps) => {
const [tripleCount, setTripleCount] = useState<number>(countFromParent * 3);
useEffect(() => {
setTripleCount(countFromParent * 3);
}, [countFromParent]);
return (
<div>
<h1>Child triple counter</h1>
<p>{tripleCount}</p>
</div>
);
};
第二个孩子收到来自父母的回调函数,改变父母的状态:
type DoubleForParentProps = { doubleCallback: () => void };
// Receives a function as prop, used to change state of the parent
const DoubleForParent = ({ doubleCallback }: DoubleForParentProps) => {
const handleButtonClick = () => {
doubleCallback();
};
return (
<div>
<h1>Child double counter</h1>
<button onClick={handleButtonClick}>Double the parent count</button>
</div>
);
};
对于您的第三种情况(孩子 孩子),有很多不同的选择。第一个显然在其父级中保持状态并将其传递给两个子级,类似于本示例中的父级。
如果您有孙子或组件在树中的距离更远,那么使用某种状态管理解决方案可能是有意义的。大多数时候,内置的React context 是完全足够的。如果您想了解有关上下文的最佳实践,我强烈推荐 Kent C. Dodds' blog post。这也将帮助您更好地了解 React 生态系统。
在我看来,外部状态库是 a) too complex as a beginner、b) really new and not battle proven 或 c) not a best practice anymore or overblown。