¿Es una forma de cambiar dinámicamente a los hijos de un componente? Tengo un componente que envuelve a otros componentes, recorre recursivamente a los niños, lo que quiero es cambiar el texto de los niños que son cadenas. p.ej
render() { const func = (node) => { React.Children.forEach(node.children, (childNode) => { if (childNode && childNode.props && typeof childNode.props.children === "object") { func(childNode.props); } else if (typeof childNode.props.children === "string"){ console.log(childNode.props); } }) } func(this.props); return <span>{ this.props.children }</span>; }Establecer childNode.props.children === "algo" dentro de else está fallando, los niños son de solo lectura. ¿Alguna idea de cómo puedo lograr lo que quiero?
Los accesorios de React son de solo lectura, de hecho, como se indica en los documentos de React. Puede seguir el enfoque JSX, que siempre crea un nuevo elemento, en lugar de cambiar los accesorios de elementos existentes. En una etapa posterior, el elemento se reconcilia con el componente React existente en el DOM virtual.
Para cambiar los accesorios del elemento a través de JavaScript, puede clonar el elemento usando el método React.cloneElement . Tenga en cuenta que, en este caso, no debe generar this.props.children, sino generar un nuevo árbol de elementos resultante:
render() { const func = (children) => { return React.Children.map(children, (childNode) => { if (typeof childNode === "string") return "something"; // cover case: <div>text<div></div></div> if (typeof childNode.props.children === "string") return React.cloneElement(childNode, [], "something"); return React.cloneElement(childNode, [], func(childNode.props.children)); }) } return <span>{ func(this.props.children) }</span>; }Sugeriría tener una lista dinámica de niños en el estado del componente y renderizarlos.
class Hello extends React.Component { constructor() { super(); this.state = { children: [ <div>test</div>, <div>test2</div> ] }; setTimeout(() => { this.setState({ children: [ <div>new!</div>, <div>changed!</div> ] }); }, 2000); } render() { return <p>{this.state.children}</p>; } } ReactDOM.render( <Hello />, document.getElementById('container') );Puede aplicar este concepto en su aplicación.
La solución sería iterar sobre this.props.children y crear los niños personalizados como este.
class Parent extends React.Component { constructor(props) { super(props); this.state = { no: 'need' }; } render() { let children = []; // children let k = 0; // key this.props.children.forEach( function(child) { if( "string" === typeof child.props.children ){ console.log(child); let enew = React.cloneElement( child, child.props, "new_" + k ); k++; children.push(enew); }else{ children.push(child); } }); return <span>{ children }</span>; } } var NewComponent = React.createClass({ render: function() { return ( <div className="awesome" style={{border: '1px solid red'}}> Hello World! </div> ); } }); ReactDOM.render( <Parent> <NewComponent /> <div>Hello</div> <div>World</div> </Parent>, document.getElementById('root') ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>Según su necesidad, incluso puede crear un nuevo elemento en lugar de clonar el existente.
let enew = React.createElement( 'div', {key: k, className: 'new'}, "new" );