2017-04-25 76 views
3

我有这个简单的组件,initialPlayers道具传递给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')); 

有此错误控制台,并不能值传递给Header组件作为{this.state.players}。任何想法?。

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) 
+0

的可能的复制[阵营组件从道具初始化状​​态](https://stackoverflow.com/questions/40063468/react-component-initialize-state-from-props) – jalal246

回答

2

移动设置的玩家排队到你的构造函数():

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

这是Facebook如何做到这一点,如他们的文档所示:https://reactjs.org/docs/react-component.html#constructor – Rohmer

1

你想用componentWillMount,因为它运行前组件的第一渲染 - 比较,为的componentDidMount

你需要初始化state说明

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>

0

第一否则你会得到错误更新它的价值,那么你必须使用setState米ethod改变它(这是更新的反应state推荐的方式)

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

错误地使用componentDidMount,ESlint本身会为此引发错误。相反,应该使用componentWillMount。 – Namish

+0

是的,你是对的,在这种情况下,最好的选择将是** componentWillMount ** –

相关问题