如何以编程方式更新React datetime slider picker的显示值?
我正在使用React datetime slider picker组件,不知道如何在点击按钮等场景下以编程方式更新其值。
我通过如下方式渲染该组件:
<RDSPwidget enableSecond={true} />
其中我的RDSPwidget定义如下:
import Calendar from 'react-datetime-slider-picker/dist/Calendar'; import TimePicker from 'react-datetime-slider-picker/dist/TimePicker'; import { Tabs, Tab, Button } from '@material-ui/core'; import Language from 'react-datetime-slider-picker/public/Language'; class RDSPwidget extends React.PureComponent { constructor(props) { super(props); this.state = { tab: 0, date: {year: 2000, month: 1, date: 1}, time: {hour: 1, minute: 1, second: 1}, counter: 1 }; this.onTabChange = this.onTabChange.bind(this); this.onValueChange = this.onValueChange.bind(this); this.updateValue = this.updateValue.bind(this); } onTabChange(value) { this.setState({ tab: value }); } onValueChange(isDate, value) { let date = this.state.date, time = this.state.time; if (isDate) { date = { year: value.year, month: value.month, date: value.date }; this.setState({ date: date }); } else { time = value; this.setState({ time: time }); } } updateValue() { this.setState({ date: {year: 2020, month: 10, date: 10} }); } componentWillReceiveProps(nextProps) { let that = this; this.setState({ date: nextProps.value.date, time: nextProps.value.time }); let tab = this.state.tab; this.setState({ tab: 1-tab }); setTimeout(function() { that.setState({ tab: tab }); }, 0); } render() { const language = (this.props.language === 'ko') ? Language['ko'] : Language['en']; return ( <div className='picker'> <div className='picker-tab'> <Tabs value={this.state.tab} onChange={(event, value) => this.onTabChange(value)} fullWidth textColor='inherit' classes={{ indicator: 'picker-tab-indicator' }} > <Tab label={language.date} icon={<Today />} classes={{ selected: 'selected' }} /> <Tab label={language.time} icon={<AccessTime />} classes={{ selected: 'selected' }} /> </Tabs> </div> <div className='picker-form'> {(this.state.tab === 0) ? <Calendar language={this.props.language} defaultValue={this.state.date} onChange={(date) => this.onValueChange(true, date)} /> : <TimePicker language={this.props.language} enableSecond={this.props.enableSecond} defaultValue={this.state.time} onChange={(time) => this.onValueChange(false, time)} />} </div> <button onClick={this.updateValue}>Update</button> </div> ); } }
我很久之前写的这段代码,已经忘记为什么要使用componentWillReceiveProps(nextProps)了(我对React并不熟练)。
请问如何以编程方式更改该组件显示的日期?
编辑:
问题似乎与以下条件渲染的组件有关:
<div className='picker-form'> {(this.state.tab === 0) ? <Calendar language={this.props.language} defaultValue={this.state.date} onChange={(date) => this.onValueChange(true, date)} /> : <TimePicker language={this.props.language} enableSecond={this.props.enableSecond} defaultValue={this.state.time} onChange={(time) => this.onValueChange(false, time)} />} </div>
实际上,当我在Calendar标签页时点击按钮,没有任何反应。但如果切换到TimePicker标签页再切回Calendar标签页,更新后的日期就会显示出来。
问题核心是你给Calendar和TimePicker组件用了defaultValue属性,这个属性仅在组件首次渲染时生效,后续状态更新不会触发组件刷新显示值。要实现编程式控制,需将组件改为受控组件,用value绑定状态而非defaultValue。
替换
defaultValue为value
在条件渲染的组件中,把defaultValue替换成value,绑定对应的state值:<div className='picker-form'> {(this.state.tab === 0) ? <Calendar language={this.props.language} value={this.state.date} onChange={(date) => this.onValueChange(true, date)} /> : <TimePicker language={this.props.language} enableSecond={this.props.enableSecond} value={this.state.time} onChange={(time) => this.onValueChange(false, time)} />} </div>清理废弃的生命周期逻辑
componentWillReceiveProps已经被React废弃,你之前写的切换tab逻辑是为了绕过defaultValue只初始化一次的限制。改成受控组件后,这段代码可以直接删除。如果需要从外部props接收值更新内部状态,改用componentDidUpdate:componentDidUpdate(prevProps) { if (prevProps.value !== this.props.value) { this.setState({ date: this.props.value.date, time: this.props.value.time }); } }验证效果
修改后点击Update按钮,updateValue更新date状态,Calendar组件会因value属性变化自动刷新,直接显示新日期,无需切换tab。
内容的提问来源于stack exchange,提问作者Stéphane Laurent

