Javascript 将道具传递给React中的特定嵌套子级
我正在尝试为孩子们配置一些道具 在这个虚拟示例中,我正在测试函数,以便使用以下属性专门针对任何子级(嵌套或非嵌套):Javascript 将道具传递给React中的特定嵌套子级,javascript,reactjs,Javascript,Reactjs,我正在尝试为孩子们配置一些道具 在这个虚拟示例中,我正在测试函数,以便使用以下属性专门针对任何子级(嵌套或非嵌套):swipme 如果在我的div中的渲染函数中只包含一个子项,则效果非常好,如下所示: <SwapableItems> <div> {/*the p element will get the red color as defined on childrenHandler*/} <p swipeMe>
swipme
如果在我的div
中的渲染函数
中只包含一个子项,则效果非常好,如下所示:
<SwapableItems>
<div>
{/*the p element will get the red color as defined on childrenHandler*/}
<p swipeMe>Add Props</p>
</div>
</SwapableItems>
下面是完整的脚本。
你也可以在
从“React”导入React;
从“react dom”导入react dom;
函数App(){
返回(
添加道具
不要添加道具
);
}
函数交换项({children}){
const content=childrenHandler(子项,{style:{color:{red}});
返回内容;
}
const childrenHandler=(children,swipeprops)=>{
const childEls=React.Children.toArray(Children.map)((child)=>{
const childHasChildren=
child.props.children&&React.isValidElement(child.props.children)
?childrenHandler(child.props.children,swipeprops)
:未定义;
返回孩子的孩子
?React.cloneElement(child,{},childHasChildren)
:child.props.swipme
?React.cloneElement(子级,{…swipeprops})
:React.cloneElement(子元素,{});
});
返回儿童;
};
const rootElement=document.getElementById(“根”);
render(,rootElement);
child.props.children
是一个数组,因此React.isValidElement(child.props.children)
总是错误的,要修复它,请尝试在其上使用React.cloneElement
:
React.isValidElement(React.cloneElement(child.props.children)); // true
样式重置示例:
const styleA = {
color: "blue"
};
const InlineReset = ({ children }) => {
return React.Children.map(children, child => {
console.log(child.props);
return React.cloneElement(child.props.children, { style: null });
});
};
export default function App() {
return (
<InlineReset>
<div>
<h1 style={styleA}>Hello </h1>
</div>
</InlineReset>
);
}
const styleA={
颜色:“蓝色”
};
常量InlineReset=({children})=>{
返回React.Children.map(Children,child=>{
console.log(child.props);
返回React.cloneElement(child.props.children,{style:null});
});
};
导出默认函数App(){
返回(
你好
);
}
我测试了这项工作。
如果有孩子的话,我用SwapableItems包装嵌套的孩子
函数交换项({children}){
constprops={style:{color:{red}};
返回子项。映射(子项,(子项)=>{
让nestedChild=child.props.children;
const hasNestedChild=nestedChild&&typeof nestedChild!==“string”
if(hasNestedChild){
nestedChild={nestedChild};
}
返回儿童。道具?swipeMe | |已嵌套儿童
?cloneElement(child,child.props?.swipme?props:{},[nestedChild])
:儿童;
});
}
这就是解决方案:
我已经初始化了一个变量
,它将把递归
保存在逻辑之外且未定义
let childhas children代码>
我将代码封装在一个if
语句中,并进行了一些修改:
如果子项
有子项,则为数组
或对象
,如果在传递的子项
中存在有效的React
元素
为了无错误地传递递归,如果调用了if
语句中的代码,我克隆了一个过滤器/单个对象,子对象将是有效元素,然后我只将这些/这个传递到递归中:
const validChildren = arrayOfChildren
? deeperChildren.filter((c) => React.isValidElement(c))
: deeperChildren;
这是你的电话号码
现在它接受一个带有子项的项或一个数组。这可以配置为动态传递道具,使用默认道具和其他可以从组件外部传递的道具,尽管后者不是我的情况。需要此解决方案是为了在不使用这些解决方案的情况下实现更复杂的内容,例如渲染道具
、道具合同、HOC等
const childrenHandler = (children, swipeMeProps) => {
const childEls = React.Children.toArray(children).map((child) => {
let childHasChildren;
const deeperChildren = child.props.children;
const arrayOfChildren = Array.isArray(deeperChildren);
const singleChildren =
typeof deeperChildren === "object" && deeperChildren !== null;
if (
(arrayOfChildren &&
deeperChildren.some((c) => React.isValidElement(c))) ||
(singleChildren && React.isValidElement(deeperChildren))
) {
const validChildren = arrayOfChildren
? deeperChildren.filter((c) => React.isValidElement(c))
: deeperChildren;
childHasChildren = childrenHandler(validChildren, swipeMeProps);
}
return childHasChildren
? React.cloneElement(child, {}, childHasChildren)
: child.props.swipeMe
? React.cloneElement(child, { ...swipeMeProps })
: React.cloneElement(child, {});
});
return childEls;
};
你好,丹尼斯。我想用两个孩子作为道具传递元素。这就是为什么我在寻找一种更深层的嵌套解决方案。您的解决方案根本不需要任何递归。我用错误的方式命名了这个组件。让我们称之为
。我想像这样在其中传递数据,以便有一个或多个子项:我的消息隐藏在消息下
因此问题在于React.isValidElement(child.props.children)
,将递归函数更改为接受单个元素我不理解在传递的元素有子元素并且这些子元素必须是元素的情况下触发递归的错误。我想我已经理解了我添加React.isValidElement(child.props.children)
时的意思。请你解释一下,你只接受一个孩子是什么意思?请注意,我可能会传递一个子对象列表,所有子对象都包含两个子对象。我希望映射这些包装,然后检查每个包装的子对象,然后根据配置将道具添加到其中任何一个,在本例中,如果其中一个有swipme
作为prop
。在您的情况下反应。isValidElement(child.props.children)
总是错误嘿!我已在此codesandBox检查了您的解决方案,但它对我无效:。你能检查一下吗?我刚刚发布了我想要的行为。你能检查一下我发给你的链接上的答案吗?我以前从未见过这种map
语法,也从未想过递归地传递整个组件。这将重新运行整个组件,对吗?我修复了>这将重新运行整个组件,对吗?没关系,因为它只是一个逻辑组件,没有任何东西会呈现给DOM。但这样做的好处是,您可以在每个嵌套子级中使用挂钩,因此您的状态更改可能会有更好的性能。感谢您的解决方案。问题是它确实克隆了所有元素。我一直在寻找一种只克隆具有特定属性的元素的解决方案。
const deeperChildren = child.props.children;
const arrayOfChildren = Array.isArray(deeperChildren);
const singleChildren =
typeof deeperChildren === "object" && deeperChildren !== null;
if (
(arrayOfChildren &&
deeperChildren.some((c) => React.isValidElement(c))) ||
(singleChildren && React.isValidElement(deeperChildren))
) {
const validChildren = arrayOfChildren
? deeperChildren.filter((c) => React.isValidElement(c))
: deeperChildren;
const childrenHandler = (children, swipeMeProps) => {
const childEls = React.Children.toArray(children).map((child) => {
let childHasChildren;
const deeperChildren = child.props.children;
const arrayOfChildren = Array.isArray(deeperChildren);
const singleChildren =
typeof deeperChildren === "object" && deeperChildren !== null;
if (
(arrayOfChildren &&
deeperChildren.some((c) => React.isValidElement(c))) ||
(singleChildren && React.isValidElement(deeperChildren))
) {
const validChildren = arrayOfChildren
? deeperChildren.filter((c) => React.isValidElement(c))
: deeperChildren;
childHasChildren = childrenHandler(validChildren, swipeMeProps);
}
return childHasChildren
? React.cloneElement(child, {}, childHasChildren)
: child.props.swipeMe
? React.cloneElement(child, { ...swipeMeProps })
: React.cloneElement(child, {});
});
return childEls;
};