0%

React子组件从父组件接收到新的props时,没有重新渲染的问题

今天写 React 项目的时候,遇到一个比较奇怪的问题,这个问题应该也是大家在开发中经常会遇到的,问题我简单描述一下,我写了一个列表组件,然后这个列表组件引入了另一个PositionedSnackbar 组件, 这个PositionedSnackbar 组件是用于请求数据成功或者失败时给与用户提示的,起初这个PositionedSnackbar 组件是这样写的:

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
import React from 'react';
import Snackbar from '@material-ui/core/Snackbar';

class PositionedSnackbar extends React.Component {
constructor(props) {
super(props);
this.state= {
open:props.open||false,
message:props.message||'message',
vertical:props.vertical||null, // 水平方向:'left', 'center' or 'right'
horizontal:props.horizontal||null, // 垂直方向:'top' or 'bottom'
}
}

render() {
const { vertical, horizontal, open, message } =this.state;
return (
<div>
<Snackbar
anchorOrigin={{ vertical, horizontal }}
open={open}
onClose={this.handleClose}
ContentProps={{
'aria-describedby':'message-id',
}}
message={<spanid="message-id">{message}</span>}
/>
</div>
);
}
}

export default PositionedSnackbar;

通过上面的代码可以知道,子组件把父组件传递过来的props转换成了自己的state,但是我在调试的过程中发现子组件只重新渲染了一次,每次父组件传入了新的props,子组件也不会更新,我在父组件里面是这样写的:加载下一页,请求数据成功的时候,我在父组件里面setState设置openSnackBar的值为true,snackMessage的值为‘加载成功’,但是子组件没有再更新了。百思不得姐,于是百度一番,终于找出原因,自己对React的constructor理解的不够透彻,constructor方法里面通过props的值去设置子组件的state只会发生在组件初始化阶段,如果在组件渲染出来以后还需要更新它,我们需要在 react 的 componentWillReceiveProps 生命周期里手动更新state,最后解决办法是在子组件加上下面一段代码:

1
2
3
4
5
6
7
8
componentWillReceiveProps(nextProps) {
this.setState({
open: nextProps.open,
message: nextProps.message,
vertical: nextProps.vertical,
horizontal: nextProps.horizontal,
});
}

然后子组件在接收到父组件传递过来的新的rpops,子组件就可以正常更新了。另外,子组件在接收到父组件传递过来的新的rpops,要让子组件正常更新还有一种方法,就是这些props不要存到子组件的state里面,而是在子组件的render方法里,通过 this.props.xxxx 直接访问。

  • 本文作者: 前端农民工
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!