Monday, March 7, 2016

Access parent context when using this.props.children in React

Leave a Comment

Given the following, is it possible to access the parent context rather than the containers from a child (non-react component) element?

The example logs container, ideally it would log parent. I would like for Parent to be self contained, not to have it's state managed by its container.

var Container = React.createClass({   getInitialState: function () {     return {       context: 'container'     }   },   render: function () {     return (       <Parent>         <a href="#" onClick={function () {console.log(this.state.context);}.bind(this)}>click me</a>       </Parent>     );   } });  var Parent= React.createClass({   getInitialState: function () {     return {       context: 'parent'     }   },   render: function () {     return (       <div>         {this.props.children}       </div>     );   } }); 

If there is another pattern for handling this, please share as well.

Note: To be clear, I understand how the this keyword works and why the above example works as it does. The example is simply meant to illustrate the problem.

3 Answers

Answers 1

You can import some React helpers for that:

var React = require('react')  ... var children = React.Children.map(this.props.children, child => {   return React.cloneElement(child, {     context: this.state.context   }) })  render() {   return <div>{ children }</div> } ... 

Then your child component will have this.props.context which will be the string 'parent', but this must be a React component, as this needs to refer to the component using the parent prop

var YourComponent = React.createClass({   render() {      return (        <a href="#" onClick={() => console.log(this.props.context)}>          click me        </a>      )    } })  ------  var Parent = require('./Parent') var YourComponent = require('./YourComponent')  ...  render() {   return <Parent><YourComponent /></Parent> } 

Answers 2

I do not know about the first part of your question, but since you commented about dynamically creating components, here's how I do it:

You can set a state variable in the constructor of the class and its parent:

if (typeof this.state == 'undefined') {   this.state = {     componentsToRender: <div></div>   }; } 

Then in the parent component, in the componentDidMount() function:

var componentsToRender = []; if ([conditional]) {   // some logic so you know which component to render   componentsToRender.push(<customChildComponentToRender key={} />); } else {   componentsToRender.push(<otherComponentToRender key={} />); } this.setState({   componentsToRender: <div>{componentsToRender}</div> }); 

Make sure to put a key (lines 4 and 7 of the second code block) or React will scream at you.

In response to your initial question, I would watch this video from the ReactJS Conference 2015 to get more of the heart behind a container. After hearing what the guys at Facebook say (who have radical views on containers!), you might want to rethink the design to make your container more of a data layer.

Answers 3

I would check out THIS article from the react website. I think it might give you some intuition on solving your problem.

As a general rule of thumb, I try and only use this.state to handle internal UI state of a specific component. Everything else is passed via props. If you're needing the full context of a component, I would either pass it as a prop or checkout something like flux or redux which will help you manage state between components.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment