8

How can a child access its parent's props? For instance,

A parent component - footer.jsx:

import React from 'react';
import $ from 'jquery';

import NavItem from './nav-item';

class Footer extends React.Component
{
    constructor(props) {
        super(props);
        this.state = {
            publicUrl: null,
            currentUrl: null,
            navitems: [],
        };
    }

    // Then fetch the data using $.getJSON():
    componentDidMount() {
        this.serverRequest = $.getJSON(this.props.source, function (result) {
            this.setState({
                currentUrl: window.location.href,
                publicUrl: result.publicUrl,
                navitems: result.nav
            });
        }.bind(this));
    }

    componentWillUnmount() {
        this.serverRequest.abort();
    }

    render() {
        var loop = this.state.navitems.map(function(item, index){
            return <NavItem key={index} item={item}></NavItem>;
        });

        return (
            <div>
                <div className="nav">
                    <ul>{ loop }</ul>
                    <p>{this.state.publicUrl}</p>
                    <p>{this.state.currentUrl}</p>
                </div>
            </div>
        )
    }
}

export { Footer as default }

A child component - nav-item.jsx:

import React from 'react';

class NavItem extends React.Component
{
    constructor(props) {
        super(props);
    }

    render() {
        return <li><a href={this.props.publicUrl + '/' + this.props.item.url}>{this.props.item.title}</a></li>
    }
}

export { NavItem as default }

results in footer.jsx (parent):

this.props.publicUrl // http://my-website.com

results in nav-item.jsx (child):

this.props.publicUrl // undefined but it should be http://my-website.com

Any ideas?

Sample data:

{
    "publicUrl": "http:\/\/my-website.com",
    "nav": [{
        "navId": "3",
        "title": "Home
        "code": "home
        "href": null,
        "style": null,
        "sort": "3",
        "url": "home
        "parentId": null,
        "totalChildren": "0",
        "createdOn": null,
        "updatedOn": null
    }, {
        "navId": "4",
        "title": "About
        "code": "about
        "href": null,
        "style": null,
        "sort": "4",
        "url": "about
        "parentId": null,
        "totalChildren": "0",
        "createdOn": null,
        "updatedOn": null
    }, {
        "navId": "5",
        "title": "Contact",
        "code": "contact",
        "href": "#contact",
        "style": null,
        "sort": "5",
        "url": "contact",
        "parentId": null,
        "totalChildren": "0",
        "createdOn": null,
        "updatedOn": null
    }]
}
Run
  • 54,938
  • 169
  • 450
  • 748

4 Answers4

4

There is no way to access parent props in child component. you can achieve this in following two ways:-

  1. Pass values into child component from parent via props like this :- <NavItem key={index} publicUrl={this.state.publicUrl} item={item}></NavItem>.
  2. Set values in state and dispatch action from child to fetch values from state.

Also, I notice that you are setting values in state in componentDidMount, so either set default values for state in constructor OR check for undefined value in your child component

Gaurav joshi
  • 1,743
  • 1
  • 14
  • 28
  • i get this error `Uncaught TypeError: Cannot read property 'props' of undefined` for `publicUrl={this.props.publicUrl}`. – Run Nov 04 '16 at 08:54
  • I must bind `this` to the loop. see my answer below. – Run Nov 04 '16 at 09:16
4

Another solution to this is

<MyChildComponent {...this} />

This will pass all parent props to child, you can also pass specific props by

<MyChildComponent {...this.specificProps} />

Hope this helps.

happy go lucky
  • 361
  • 3
  • 13
2

I must bind this to the loop:

var loop = this.state.navitems.map(function(item, index){
            return <NavItem key={index} publicUrl={this.state.publicUrl} item={item}></NavItem>;
}.bind(this));
Run
  • 54,938
  • 169
  • 450
  • 748
0

You have to pass the value as a prop from the parent down to the child. It's not really possible otherwise.

All you have to do in your code above is this small modification:

var loop = this.state.navitems.map(function(item, index){
   return <NavItem key={index} publicUrl={this.props.publicUrl} item={item}></NavItem>;
});

Now, NavItem will have the prop publicUrl which is equal to the publicUrl prop of the parent. So basically:

results in footer.jsx (parent):

this.props.publicUrl // http://my-website.com

results in nav-item.jsx (child):

this.props.publicUrl // http://my-website.com

Alternatively, though not recommended in your case, you could pass NavItem a function as a prop. That function can be defined in your parent and returns the value of the prop (or state or whatever is local to that component).

So for example in your parent:

_getPublicUrl = () => {
  return this.props.publicUrl; //or any kind of value, local or otherwise
}
......
var loop = this.state.navitems.map(function(item, index){
   return <NavItem key={index} getPublicUrl={this._getPublicUrl} item={item}></NavItem>;
});

Then, in your NavItem you can call this function:

var parentPublicUrl = this.props.getPublicUrl();

Again, not recommended in this particular case. However, it's a useful way to get a state value or perhaps a variable that was fetched through some Ajax call or something.

Chris
  • 57,622
  • 19
  • 111
  • 137
  • thanks but i think it should be `publicUrl={this.state.publicUrl}` – Run Nov 04 '16 at 08:45
  • @teelou, well, now that you say it, it's a bit confusing if `publicUrl` is a `prop` or a `state` in your Parent. Your question reads *How a child access it's parent's props?*... "parents props" - not state. Then in your code it seems to be a `state`. Which one is it? :D --- Regardless, just use `this.state.publicUrl` if it's a state, otherwise use as shown above. – Chris Nov 04 '16 at 08:49
  • i get this error `Uncaught TypeError: Cannot read property 'props' of undefined` for `publicUrl={this.props.publicUrl}`. – Run Nov 04 '16 at 08:52
  • I must bind `this` to the loop. see my answer below. – Run Nov 04 '16 at 09:16