35

I have (e.g.) two components in React. The first, app.js, is the root component. It imports some JSON data and puts it in its state. This works fine (I can see it in the React devtools).

import data from '../data/docs.json';

class App extends Component {
  constructor() {
    super();
    this.state = {
      docs: {}
    };
  }
  componentWillMount() {
    this.setState({
      docs: data
    });
  }
  render() {
    return (
      <Router history={hashHistory}>
        <Route path="/" component={Wrapper}>
          <IndexRoute component={Home} />
          <Route path="/home" component={Home} />
          <Route path="/docs" component={Docs} />
        </Route>
      </Router>
    );
  }
}

The second, docs.js, is meant to show this JSON data. To do that it needs to access the state of app.js. At the moment it errors, and I know why (this does not include app.js). But how then can I pass the state from app.js to docs.js?

class Docs extends React.Component {
    render() {
        return(
            <div>
                {this.state.docs.map(function(study, key) { 
                    return <p>Random text here</p>; 
                })}
            </div>
        )
    }
}
GluePear
  • 7,244
  • 20
  • 67
  • 120
  • related - [How to make a shared state between two react components?](https://stackoverflow.com/q/38901106/104380) – vsync Jul 16 '18 at 19:15

3 Answers3

18

The proper way of doing this would be by passing state as props to Docs component.

However, because you are using React Router it can be accessed in a bit different way: this.props.route.param instead of default this.props.param

So your code should look more or less like this:

<Route path="/docs" component={Docs} docs={this.state.docs} />

and

{this.props.route.docs.map(function(study, key) { 
    return <p>Random text here</p>; 
})}
Has
  • 121
  • 11
pwolaq
  • 6,343
  • 19
  • 45
  • 1
    i can't send states all my 20 componentes, there is a way to do it with redux? – stackdave Oct 05 '17 at 15:27
  • 3
    This explained **nothing**. passing it is the easy part, but what then? what is the proper way to extend the child with the state of the parent so they will both share the exact same Object and not a copy of the state in the child? – vsync Jul 16 '18 at 19:12
  • @vsync if you will pass parent's state to the child as a prop, it will be the same object. – pwolaq Jul 16 '18 at 20:28
  • it will, at first. but then `setState` will be called somewhere in the child, and then the state of the child will be out-of-sync because of this new thing the new generation of developers loves so much, called immutability. horrid thing. only causes troubles. – vsync Jul 16 '18 at 21:56
  • 4
    @vsync if you want to share child's state with the parent, you should modify parent's state using callbacks and pass it down using props – pwolaq Jul 17 '18 at 07:05
4

Another way of doing this is:

<Route path="/docs" component={() => <Docs docs={this.state.docs}/>}>

If you need to pass children:

<Route path="/" component={(props) => <Docs docs={this.state.docs}>{props.children}</Docs>}>

If you are doing it like this, then you can access your props values directly by this.props.docs in Child Component:

{
    this.props.docs.map((study, key)=> { 
       return <p key={key}>Random text here</p>; 
    })
}
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
1

Another way of doing this will be

        <Route path='/' render={ routeProps => <Home 
            {...routeProps} 
            docs={this.state.docs}
            /> 
          } 
        />

While in the child component you can access docs using

this.props.docs

Hope it helps!

lavee_singh
  • 1,379
  • 1
  • 13
  • 21