0%

将props的值复制给state,可否?

当不涉及父组件传递更改的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
})
}
}

如图,子组件正常更新渲染。