当不涉及父组件传递更改的state给子组件时,是可以将props的值复制给state,但是如果需要重新定义一个父组件的state,这时候就会问题。
一般情况下,子组件接收到父组件传来的props,当做变量直接用就可以,但是个别情况下子组件需要将props赋值给state,但是这里会出现一个问题:如果父组件的state更新后,通过props将父组件的state传给子组件,子组件的state并不会更新。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| class Child extends React.Component { constructor(props) { super(props) this.state = { list: props.list } } //后期代码添加部分 //componentWillReceiveProps(props) { //this.setState({ //list: props.list //}) //}
handleCilck = () => { this.setState({ list: this.state.list.concat({ name: '小七' }) }) }
render() { console.log('我是子组件'); return ( <div> <button onClick={this.handleCilck}>点击在下方列表中添加小七</button> {this.state.list.map((item, index) => { return <h1 key={index}>Hello, {item.name}</h1> })} </div> ) } }
class Parent extends React.Component { constructor(props) { super(props) this.state = { list: [{ name: '小五' }, { name: '小六' }] } } handleClick = () => { this.setState({list: [{name: '小一,我是父组件更新的props'}]}) } render() { return ( <div> <button onClick={this.handleClick}>点击父组件更新props</button>; <Child list={this.state.list} />; </div> ) } }
ReactDOM.render( <Parent/>, document.getElementById('root') );
|
如图,子组件的props中能接收到跟新后的List,但是子组件的state并不会更新。
要解决这个问题,需要先了解组件生命周期运行机制。
1 2 3 4 5 6
| constructor(props) { super(props) this.state = { list: props.list } }
|
上面这段代码是在子组件挂载(初始化)阶段执行的,当父组件的state发生变化时,子组件的props属性就会发生改变(因为子组件是通过prop获取父组件的state.list),父组件更新,子组件也会更新,子组件更新的时候并不会去执行constructor里面的代码,而是执行conmponentWillReceiveProps()方法,所以新的子组件的的props并不会更新。
解决的方法很简单,就是把状态更新重新在conmponentWillReceiveProps()方法刷新一遍。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| componentWillReceiveProps(props) { this.setState({ list: props.list }) }
componentWillReceiveProps在初始化render的时候不会执行,它会在Component接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染。 componentWillReceiveProps中想作任何变更最好都将两个状态进行比较,假如状态有异才执行下一步。不然容易造成组件的多次渲染,并且这些渲染都是没有意义的。 代码优化
componentWillReceiveProps(nextProps) { if(nextProps.list !== this.props.list){ this.setState({ list: nextProps.list }) } }
|
如图,子组件正常更新渲染。