Aakash John
Aakash John

Reputation: 321

How to pass props to children components in React

I am developing single page application and want to pass user authentication data to children components. How can I pass and access it in children components reactjs. I am calling authentication method in app container and need to pass it down to some of its children components.

@asyncConnect([{
promise: ({ store: { dispatch, getState } }) => {
    const promises = [];
    if (!isLoaded(getState())) {
        promises.push(dispatch(loadmyauth()));
    }
    return Promise.all(promises);
}
}])
@connect(
state => ({
    user: state.auth.user
}))
export default class App extends Component {
static propTypes = {
    children: PropTypes.object.isRequired,
    user: PropTypes.object
};
static contextTypes = {
    store: PropTypes.object.isRequired
};
constructor(props) {
    super(props);
    var user = {
        auth :'false',
        account_type : 'N',
        profile_pic : null,
        useremail : null,
        userid : null,
        username : null,
        FNAME : null,
        LNAME : null,
    }

    this.state = {
        user: props.user,
        authloaded: false,
    }
}
render() {
    const { children } = this.props;
    return (
        <div>
            <Helmet {...config.app.head}/>
            <Header user={this.state.user} />
            <div className="mainapp-content">{this.props.children}</div>
        </div>
    );
}
}

Upvotes: 2

Views: 1177

Answers (3)

Aakash John
Aakash John

Reputation: 321

I have came across solution to this by using redux to manage state of application. I do state local to each component with react and redux to keep data. When I want to change data I change it at locally with react state and also with redux data, so it keep data in synchronization.

Upvotes: 1

Frank
Frank

Reputation: 2198

If you are using redux than I don't think you set state in your app component. Instead state is handle in the redux store and passed to your app component as props. But I could be wrong, I am not a redux expert.

If you want to handle state at your app component and pass it down via context this should get you started.

import React from 'react';
import _ from 'underscore';

var AppHeader = React.createClass({

  contextTypes: {
    appManager: React.PropTypes.object
  },
  render() {

    return <div>
              <b>First Name:</b><span>{this.context.appManager.User.FirstName}</span><br/>
              <b>Last Name:</b><span>{this.context.appManager.User.LastName}</span><br/>
           </div>
  }

});

var App = React.createClass({

  getInitialState() {
    return {
      User: {
         FirstName: '',
         LastName: ''
      }
    }
  },
  childContextTypes: {
        appManager: React.PropTypes.object
  },
  getChildContext() {
        return {
            appManager: {
                User: _.extend({}, this.state.User)
            }
        }
  },
  setUserInfo() {

    if (this.state.User.FirstName == 'Homer') {
      this.setState({
        User: { FirstName: 'Peter', LastName: 'Griffin' }
      });  

    } else {
      this.setState({
        User: { FirstName: 'Homer', LastName: 'Simpson' }
      });
    }
  },
  render() {
    return <div>
      <h1>My App!</h1>
      <input type="button" value="Update User Stat!" onClick={this.setUserInfo} />
      <h3>Header Info</h3>
      <AppHeader/>
      <h3>The Content</h3>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi lacus turpis, bibendum sit amet finibus nec, imperdiet ut nisi. Maecenas et orci vitae ante convallis iaculis at sit amet augue. Fusce est libero, interdum vitae interdum id, auctor eu ex. Donec pretium quis nibh et ornare. Donec sodales elit at vehicula rhoncus. In facilisis facilisis sem a tristique. Sed non nulla nec velit maximus aliquet sit amet vitae eros. In finibus tortor ut ipsum porttitor, et ullamcorper lorem facilisis. Sed porttitor turpis ac vulputate porta. Fusce gravida tellus elit, sed feugiat sapien tincidunt ut. Maecenas augue purus, dictum id eros a, tincidunt fringilla nisi. In eros neque, pulvinar ac velit vel, fermentum facilisis justo. Phasellus laoreet egestas tortor, id tincidunt eros tempus et. Morbi et diam ut ante sodales eleifend et eu lacus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec sodales eget ex sit amet interdum.
      </p>
      </div>
  }
})

export default App;

For context to work you need to set it up in both components. One needs to be the provider and the others need to be receivers. In your case, the App component needs to provide the context to its children by defining the context with a childContextTypes property and a getChildContext method.

childContextTypes: {
        appManager: React.PropTypes.object
  },
  getChildContext() {
        return {
            appManager: {
                User: _.extend({}, this.state.User)
            }
        }
  },

then in your child components mark them as receivers using the contextTypes property like so:

contextTypes: {
    appManager: React.PropTypes.object
  },

by doing this you link these two components without passing props directly. The child component will be able to use this.context.[whatever you provided in the parent, in this case 'appManager'].[Any method or property definded on 'appManager', in this case 'User']

The user property will be a copy of the user state in the App component.

User: _.extend({}, this.state.User)

In this example if you click the button it will change the state in the App component which will update all child components via the context. To see this in action I made a webpackbin you to play with.

Granted this is useful only if you don't know what your children will be but still need to provide them data. A simpler solution would be to pass the user as props to the child directly.

Upvotes: 1

VladFr
VladFr

Reputation: 835

I found MobX is a good state manager and it works very well with React. You can make use of React's context through a <Provider> component.

let store = observable({
  userInfo: myUserInfo
});

Then wrap your app in the node:

<Provider store={store}>
<MainAppNode>
</Provider>

In your component, access the store by decorating your component as such:

import { observer, inject } from 'mobx-react'
@inject("store") @observer class AddBar extends React.Component {
    //access your store with this.props.store
}

Upvotes: 0

Related Questions