起因:多个页面需要用到一个时间选择器,时间选择器的初始化代码比较繁多,有必要提取为一个组件。
image.png但是这个时间选择属于表单查询数据条件的一部分。表单使用了getFieldDecorator包装校验,因此表单控件会自动添加 value、onChange,数据同步将被 Form 接管。所以自定义控件不能有这两个属性,也就不能显性的去定义value、onChange去操作数据了。
就出现了问题,表单初始化数据initialValue怎么传进去,表单重置数据resetFields怎么传进去, 时间选择器得到的时间怎么传出来。
归结为两个问题,
1.父组件表单的数据设置需要传给子组件;
2.子组件变化的数据要回传给父组件;
然后去搜了一下,发现问题2的答案比较好找,修改时间选择器即子组件的数据,传递到外部还是比较好实现的,就是要调用父组件的onChange去触发一下,onChange的数据格式只要父组件子组件统一就行了。
class RangePickerSimple extends Component {
...
hourOnChange (value) {
this.props.onChange({
startDate:value[0],
endDate:value[1]
});
this.setState({
date:value
})
}
...
}
export default RangePickerSimple
问题1的话找了比较久,有这个需求的人感觉都不多。。。最后发现是要用到componentWillReceiveProps这个函数
当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用
class RangePickerSimple extends Component {
...
componentWillReceiveProps(nextProps) {
if ((nextProps.value && nextProps.value.startDate)) {
this.setState({
date:[nextProps.value.startDate, nextProps.value.endDate]
})
} else {
this.setState({
date:[]
})
}
}
...
}
export default RangePickerSimple
父组件调用
<Form.Item label={`发送时间:`}>
{getFieldDecorator('sendDate', {
initialValue:{ startDate:this.state.startTime, endDate:this.state.endTime}
})(
<RangePickerSimple key='sendDate'/>
)}
</Form.Item>
父组件重置表单
this.props.form.resetFields([
'sendDate',
]);
更新:
componentWillReceiveProps不建议使用了
新方法
static getDerivedStateFromProps(nextProps,prevState){
//该方法内禁止访问this
if(nextProps.email !== prevState.email){
//通过对比nextProps和prevState,返回一个用于更新状态的对象
return {
value:nextProps.email
}
}
//不需要更新状态,返回null
return null
}
https://www.jianshu.com/p/2091e7a2c36a
https://www.oschina.net/question/1457455_2305310
https://zhuanlan.zhihu.com/p/89494013
网友评论