我正在尝试添加一个"位置";prop到"Child"组件,并在"Parent"组件中使用它,因此"PositionWrapper"的唯一目的是添加一个prop并返回新的子级。问题是,当我在"Parent"内部调用props.children时,我会得到一个"PositionWrapper"组件,而不是我想要的"Child"组件我知道我可以调用props.children.rops.children,我会得到"Child"组件,但这个解决方案看起来不像是动态的(如果我删除了"PositionWrapper"怎么办?或者如果添加更多的包装器怎么办?(
有人知道最佳/更好的解决方案吗(或者我是否正确执行了"PositionWraper"?(
谢谢!
代码:
Child.js:
const Child = (props) => {
return (
<>
<p>my id is :{ props.id}</p>
<p>my position is : {props.position} </p>
</>
)
}
export default Child;
PositionWrapper.js:
import React from "react"
const PositionWrapper = (props) => {
return (
React.Children.toArray(props.children).map((child)=> React.cloneElement(child, { position: [0,0,0]}))
)
}
export default PositionWrapper;
Parent.js:
import React from "react";
const Parent = ( props) => {
// here I want to do things with children components of type 'Child' but props.children consists 'Wrapper' Component.
return (
props.children
)
}
export default Parent;
App.js:
import './App.css';
import PositionWrapper from './Wrapper'
import Child from './Child';
import Parent from './Parent'
function App() {
return (
<Parent>
<PositionWrapper>
<Child id ={1} />
<Child id ={2} />
</PositionWrapper>
</Parent>
);
}
export default App;
既然你想在Parent中使用位置道具,为什么不把它传递给Parent?
无论如何,uou应该在这个场景中使用高阶组件。
检查:https://reactjs.org/docs/higher-order-components.html
您可以执行一个完整的虚拟DOM树搜索,以便只将道具传递给特定类型,如下所示。这是一个简单的递归函数,执行深度优先遍历。
我们处理子项的子项,并将其作为React.cloneElement的第三个参数传递。
React.cloneElement(element,[config],[…children](
const Child = (props) => {
return (
<React.Fragment>
<p>my id is :{props.id}</p>
<p>my position is : {props.position} </p>
</React.Fragment>
);
};
const PositionWrapper = (props) => {
return React.Children.toArray(props.children).map((child) =>
React.cloneElement(child)
);
};
const Parent = (props) => {
// here I want to do things with children components of type 'Child' but props.children consists 'Wrapper' Component.
return passPositionPropToChildren(props.children, [1, 2, 3]);
};
const passPositionPropToChildren = (children, position) => {
return React.Children.toArray(children).map((child) => {
// Process the childrens first - depth first traversal
const childrenOfChildren =
child.props && child.props.children
? passPositionPropToChildren(child.props.children, position)
: null;
return React.isValidElement(child)
? React.cloneElement(
child,
child.type.name === "Child"
? {
...child.props,
position: position
}
: child.props,
childrenOfChildren
)
: child;
});
};
function App() {
return (
<Parent>
abc
<h2>hey</h2>
<PositionWrapper>
<Child id={1} />
<Child id={2} />
<div>
<Child id={3} />
</div>
</PositionWrapper>
<Child id={4} />
</Parent>
);
}
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>