问题描述
我有一个包装器组件,该组件根据其自身的状态(isDeleted
)有条件地呈现其子级。基本上,我有一个“可删除的项目”组件,如果单击按钮将其删除,则该项目本身将从DOM中删除(通过返回一个空的ReactNode即 >)。问题是,我不知道如何将按钮单击事件(作为包装器的子项出现)传递给包装的组件本身:
export default function App() {
return (
<DeleteableItemComponent>
{/* lots of other markup here */}
<button onClick={triggerFunctionInsideDeletableItemComponent}>
</DeleteableItemComponent>
)
}
以及我的可删除项目组件的最基本版本:
export default function DeleteableItemComponent() {
const [isDeleted,setIsDeleted] = useState(false);
const functionIWantToFire = () => {
// call API here to delete the item serverside; when successful,'delete' on frontend
setIsDeleted(true)
}
if (isDeleted) {
return <></>
}
return <>{children}</>
}
非常简单,我只想从按钮functionIWantToFire
回调中调用onClick
。
如何通过钩子正确完成此操作?我曾考虑过使用上下文API,但从未见过它用于触发函数触发,仅用于设置值,在这种情况下,我想触发事件本身,而不是将特定值传递给包装器组件。我也不能仅通过传递布尔属性来正确地做到这一点,因为那样的话我只能设置一次,即从false
到true
。
解决方法
您可以使用React.cloneElement
API将道具传递给您的孩子,而使用React.children.map
对其进行遍历。
React.Children.map(children,(child) => {
return React.cloneElement(child,{ /* .. props here */ });
});
一个简单的例子就是。 您可以查看示例here
function App() {
return (
<Delete>
<Child1 />
<Child2 />
</Delete>
);
}
function Delete({ children }) {
const [clicked,setClicked] = React.useState(0);
const inc = () => setClicked(clicked + 1);
const dec = () => setClicked(clicked - 1);
return React.Children.map(children,(child) => {
return React.cloneElement(child,{ inc,clicked,dec });
});
}
function Child1(props) {
return (
<div>
<p>{props.clicked}</p>
<button onClick={props.inc}>Inc</button>
</div>
)
}
function Child2(props) {
return (
<div>
<button onClick={props.dec}>Dec</button>
</div>
)
}