1. 场景描述
在做个人项目的时候, 发现了一个问题: ant design UI 框架中, Select 组件的 defaultValue 属性失效了, 即设置了defaultValue 值缺没有默认的选定内容;
上面这个问题可以抽象成为如下沙盒:
PS: 该沙盒最好在codesandbox 网站下运行
import React from "react";
import { Select } from 'antd';
const { Option } = Select;
import 'antd/dist/antd.css'
const log = console.log.bind(console)
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
}
}
// 1. 当生命周期函数为componentDidMount 时, 执行的顺序应该为:
// constructor -> render -> componentDidMount -> render;
// 而控制台显示执行了4次render, 这是为什么?
// 2. 当生命周期函数为componentDidMount 时, 在最后一次执行render时,
// defaultValue 属性已经被赋值为here, 为什么这个属性没有效果
// componentDidMount() {
// this.setState({
// defaultValue: 'here'
// })
// }
// 3. 当生命周期函数为componentWillMount 时, 执行的顺序为:
// constructor -> componentWillMount -> render(加载过程默认的)-> render(this.setData 更新过程触发的);
// 那么为什么两次控制台输出都是here, 这是由于consolo.log 的限制造成的吗?
// componentWillMount() {
// this.setState({
// defaultValue: 'here'
// })
// }
render() {
let {defaultValue} = this.state
log('执行了render 函数 defaultValue = ', String(defaultValue))
return (
<>
<Select value={defaultValue} style={{ width: 120 }}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="here">
here
</Option>
<Option value="Yiminghe">yiminghe</Option>
</Select>
</>
)
}
}
export default App
2. 问题描述即解答
2.1 组件渲染两次?
当生命周期函数为componentDidMount 时, 执行的顺序应该为: constructor -> render -> componentDidMount -> render; 而控制台显示执行了4次render, 这是为什么?
运行结果:
上面的沙盒(demo)运行环境为: codesandbox, 如果是在本地自建React 项目, 将不会运行4次, 而应该是2次
因为 React 在 Dev mode 下会刻意执行两次渲染,以防止组件内有什么 side effect 引起 bug,提前预防; 详细内容可以参见如下地址: 为什么 react 的函数组件每次渲染执行两次?
2.2 ant design Select defaultValue 属性失效
当生命周期函数为componentDidMount 时, 在最后一次执行render时, defaultValue 属性已经被赋值为here, 为什么这个属性没有效果
因为组件第一次加载的时候会取defaultValue,之后重新渲染将不会处理defaultValue。如果重新渲染组件时, 还需要加载默认值, 则使用value 属性; 详细内容可以参见如下地址: ant design Select API
其实这个严格上来说是自己没有好好看文档, 先入为主了.
2.3 componentWillMount 生命周期
当生命周期函数为componentWillMount 时, 执行的顺序为: constructor -> componentWillMount -> render(加载过程默认的)-> render(this.setData 更新过程触发的);那么为什么两次控制台输出都是here, 这是由于consolo.log 的限制造成的吗?
首先输出两次的原因是因为组件渲染了两次, 这个可以参考第一个问题;
当生命周期函数为componentWillMount 时, 如果在componentWillMount 生命周期中使用this.setData, 此时this.setData 是一个同步函数, 而非异步函数, 因此render 中defaultValue 的值为 here
值得说明的是 componentWillMount 该生命周期函数已不被官方所推荐, 因此尽量不要使用. 具体内容可以参考如下地址: React 官方文档
this.props 数据应该只在子组件负责渲染; this.props 数据更改应该发生在父组件, 这样更符合生命周期设计(componentWillReceiveProps生命周期方法已不被官方推荐