Estoy tratando de agregar un accesorio de "posición" a los componentes 'Niño' y usarlo dentro del componente 'Padre', por lo que el único propósito de 'PositionWrapper' es agregar un accesorio y devolver los nuevos elementos secundarios. El problema es que cuando llamo a props.children dentro de 'Parent' obtengo un componente 'PositionWrapper' en lugar de componentes 'Child' como quiero. Sé que puedo llamar a props.children.props.children y obtendré los componentes 'Niño', pero esta solución no parece dinámica (¿Qué sucede si elimino el 'PositionWrraper'? ¿O si agrego más envoltorios? )
¿Alguien conoce una solución óptima/mejor? (¿O estoy implementando el 'PositionWraaper' correctamente?)
¡Gracias!
El código:
Niño.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;Padre.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;aplicación.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;¿Por qué no le pasas la propiedad de posición a Parent, ya que quieres usarla en Parent?
De todos modos, debe usar High-Order-Component para este escenario.
Verifique: https://reactjs.org/docs/higher-order-components.html
Puede realizar una búsqueda completa del árbol DOM virtual para pasar los accesorios solo a un tipo específico como el que se muestra a continuación. Esta es una función recursiva simple que realiza un recorrido primero en profundidad.
Procesamos los hijos del hijo y lo pasamos como el tercer argumento de React.cloneElement .
React.cloneElement( elemento, [config], [...niños] )
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>