最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Change the children of a component dynamically in React - Stack Overflow

programmeradmin0浏览0评论

Is it a way to change the children of a component dynamically? I have a component which wraps other components, recursively walks the children, what I want is to change the text of the childrens that are string. e.g.

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 the else is failing, children is read-only. Any idea how I can achieve what I want?

Is it a way to change the children of a component dynamically? I have a component which wraps other components, recursively walks the children, what I want is to change the text of the childrens that are string. e.g.

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 the else is failing, children is read-only. Any idea how I can achieve what I want?

Share Improve this question asked Jan 22, 2017 at 20:06 Avraam MavridisAvraam Mavridis 8,92021 gold badges86 silver badges135 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 9

React props are read only indeed as it stated in React docs. You can follow JSX approach, which always creates new element, instead of changing existing element props. At later stage element is reconciled with existing React component in the Virtual DOM.

To change props of the element via JavaScript you can clone element using React.cloneElement method. Please note, you should not render this.props.children in this case, instead render new resulting element tree:

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

I'd suggest having dynamic children list in state of the component and render them.

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

You can apply this concept in your app.

The solution would be to iterate over the this.props.children and to create the custom children like this.

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>

Based on your need you may even create new element instead of cloning the existing one.

let enew = React.createElement( 'div',  {key: k, className: 'new'}, "new" );
发布评论

评论列表(0)

  1. 暂无评论