Robin
Robin

Reputation: 5486

How to pass props (both states and functions) to the child router component

Please bear with me. I just learning Reactjs and stuck at a point.

app-client.js

ReactDOM.render((
    <Router history={hashHistory}>
        <Route path="/" component={APP}>
            <IndexRoute component={Audience}/>
            <Route path="speaker" component={Speaker}/>
            <Route path="board" component={Board}/>
        </Route>
    </Router>
), document.getElementById('react-container'));

APP.js

var APP = React.createClass({

    getInitialState() {
        return {
            status: 'disconnected',
            title: ''
        }
    },

  emit(eventName, payload) {
        this.socket.emit(eventName, payload);
    },

  render() {
    return (
        <div>
            <Header title={this.state.title} status={this.state.status}/>
            {this.props.children}
        </div>
        );
  }
});

Audience.js:

var Audience = React.createClass({
    render() {
        return (<h1>Audience: {this.props.title}</h1>);
    }
});

The page is showing all the components, but this.props.title is not showing in the page, and the emit() is not firing. How do I pass the props to {this.props.children} (i.e., Audience or Speaker) on the APP?

update:

APP.js render():

render() {
    const _this = this;
    return (
        <div>
            <Header title={this.state.title} status={this.state.status}/>
            { React.children.map(this.props.children, (child, index) => {
                    //Get props of child
                   // const childProps = child.props;

                   //do whatever else you need, create some new props, change existing ones
                   //store them in variables

                   return React.cloneElement(child, {
                       // ...childProps, //these are the old props if you don't want them changed
                       // ...someNewProps,
                       // someOldPropOverwritten, //overwrite some old the old props
                       ..._this.state,
                       emit: _this.emit
                   });
                })
            }
        </div>
        );
  }

});

Upvotes: 4

Views: 750

Answers (2)

Pmon
Pmon

Reputation: 351

Iterate parent element using Api React.children and clone each element using React.cloneElement

var Child = React.createClass({
  render: function() {
        return (<div onClick={() =>  this.props.doSomething(this.props.value)}>Click Me</div>);
  }
});


var Audience = React.createClass({
  render: function() {
        return (<div>{this.props.title}</div>);
  }
});

var App = React.createClass({

  doSomething: function(value) {
    console.log('child with value:', value);
  },

  render: function() {
    var childrenWithProps = React.Children.map(this.props.children, (child) => React.cloneElement(child, { title: "test", doSomething: this.doSomething }));
    return <div>{childrenWithProps}</div>
  }
});

ReactDOM.render(
  <App>
    <Child value="2"/>
    <Audience/>
  </App>,
    document.getElementById('container')
);

https://jsfiddle.net/ysq2281h/

Upvotes: 1

Elod Szopos
Elod Szopos

Reputation: 3526

There's a combination of APIs that React provides you with that will take care of exactly what you're not certain about of how to achieve ( way to pass props to components rendered by this.props.children )

First, you need to take a look at cloneElement

It will basically take a React element, clone it, and return another with props that you can change, alter or replace entirely based on your needs.

Furthermore, combine it with the Children Utilities - loop through the children that were provided to your top level component and make the necessary changes to each element individually.

You can find a more comprehensive answer that I provided on a very similar topic for a question that was asked recently below:

changing-components-based-on-url-with-react-router

Basically, something along the lines of:

render() {
  const _this = this;
  return (
    {React.Children.map(this.props.children, (child, index) => {
       //Get props of child
       const childProps = child.props;

       //do whatever else you need, create some new props, change existing ones
       //store them in variables

       return React.cloneElement(child, {
           ...childProps, //these are the old props if you don't want them changed
           ...someNewProps,
           someOldPropOverwritten, //overwrite some old the old props
           ..._this.state,
           someFn: _this.someFn,
           ...
       });
     )}
}

Upvotes: 1

Related Questions