今天写 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 直接访问。