How can I set the state from the props passed to the component in react?
I have this simple component, the initialPlayers
props are passed to the component App
.
import React from 'react';
import ReactDOM from 'react-dom';
var PLAYERS = [
{
name: "xyz",
score: 123
}
];
// App component
class App extends React.Component {
constructor() {
super();
}
componentDidMount() {
this.state = {
players: this.props.initialPlayers
}
}
render() {
return(
<div>
<Header players={this.state.players} />
</div>
);
}
}
// Render component
ReactDOM.render(<App initialPlayers={ PLAYERS }/>,
document.getElementById('root'));
Take this error in console and won't be able to pass the value Header
as {this.state.players}
. Any idea?
Uncaught TypeError: Cannot read property 'players' of null
at App.render (bundle.js:14379)
at bundle.js:20173
at measureLifeCyclePerf (bundle.js:19452)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (bundle.js:20172)
at ReactCompositeComponentWrapper._renderValidatedComponent (bundle.js:20199)
at ReactCompositeComponentWrapper.performInitialMount (bundle.js:19739)
at ReactCompositeComponentWrapper.mountComponent (bundle.js:19635)
at Object.mountComponent (bundle.js:4667)
at ReactCompositeComponentWrapper.performInitialMount (bundle.js:19748)
at ReactCompositeComponentWrapper.mountComponent (bundle.js:19635)
source to share
You want to use componentWillMount
because it executes before , the component renders first - compare that with the descriptioncomponentDidMount
var PLAYERS = [
{ name: "xyz", score: 123 },
{ name: 'abc', score: 111 },
{ name: 'def', score: 222 }
];
const Header = ({players}) =>
<ul>{players.map(({name,score}) =>
<li><span>{name}</span><span>{score}</span></li>)}</ul>
// App component
class App extends React.Component {
// get rid of constructor if you're not doing anything with it
// constructor() { ... }
// use componentWillMount instead of componentDidMount
componentWillMount() {
this.setState({
players: this.props.initialPlayers
})
}
// don't wrap everything in a div if it not necessary
render() {
return <Header players={this.state.players} />
}
}
// Render component
ReactDOM.render(<App initialPlayers={ PLAYERS }/>,
document.getElementById('root'));
span {
display: inline-block;
font-weight: bold;
margin-right: 1em;
}
span ~ span {
font-weight: normal;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
source to share
You first need to initialize yours state
, otherwise you will get an error updating its value, then you have to use a method setState
to change it (this is the recommended update way state
in react)
import React from 'react';
import ReactDOM from 'react-dom';
var PLAYERS = [
{
name: 'xyz',
score: 123
}
];
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
players: []
};
}
componentDidMount() {
this.setState({
players: this.props.initialPlayers
});
}
render() {
return(
<div>
<ul>
{this.renderPlayers()}
</ul>
</div>
);
}
renderPlayers() {
return this.state.players.map((player, index) =>
<li key={index}>{`name: ${player.name} - score: ${player.score}`}</li>
);
}
}
ReactDOM.render(
<App initialPlayers={ PLAYERS }/>,
document.getElementById('root')
);
source to share