Dynamically change component children in Response

Is this a way to dynamically change child elements of a component? I have a component that wraps other components, walks them recursively, I want to change the text of the child strings, which are strings. eg.

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>;
}

Setting childNode.props.children === "something" inside else is not performed, children are read-only. Any idea how I can achieve what I want?

+4
source share
3 answers

, React. JSX, , . React DOM.

JavaScript, , React.cloneElement. , this.props.children, :

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>;
}
+5

.

JSFiddle

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')
);

.

+3

, this.props.children , .

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>
Hide result

According to your needs, you can even create a new element instead of cloning an existing one.

let enew = React.createElement( 'div',  {key: k, className: 'new'}, "new" );
+1
source

Source: https://habr.com/ru/post/1667499/


All Articles