简体   繁体   中英

How to set state from props that is passed to the component in react?

I have this simple component, initialPlayers props is passed to App component.

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'));

Have this error in console, and not able to pass value to Header component 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)

Move the setting players line into your constructor():

constructor(props) {
  super(props);
  this.state = {
    players: this.props.initialPlayers
  };
}

You want to use componentWillMount because it runs before the component's first render – compare that to the description of componentDidMount

 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's 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> 

First you need to initialize your state otherwise you'll get error updating it's value, then you have to use setState method to change it (this is the recommended way to update 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')
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM