ReactJS:在模糊时保存输入值,而不是在每个击键时保存输入值
我已经创建了一个反应视图,比如MyView
,它有两个文本输入,它们的初始值将由Parent Read从数据库中传递。
我还希望将更改的值保存回数据库。因此,还会为该视图传递一个相同的回调函数。
考虑到数据库保存操作很繁重,不应频繁执行。因此,我决定监听onBlur
事件,而不是输入框上的onChange
事件,因为在每次击键时都会调用onChange
。
第一种方法:
class MyView extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<input type="url" value={this.props.values.A}
onBlur={(evt)=>{this.props.saveValue('A', evt.target.value)}} />
<input type="url" value={this.props.values.B}
onBlur={(evt)=>{this.props.saveValue('B', evt.target.value)}} />
<button type="button" onClick={this.props.resetValues}>Reset</button>
</div>
);
}
}
但是,这并不起作用,因为React
强制控制输入(具有value
属性)总是伴随onChange
侦听器。
第二种方法:
因此,我尝试将这些输入设置为uncontrolled
。也就是说,使用defaultValue
而不是value
属性。
<input type="url" defaultValue={this.props.values.A}
onBlur={(evt)=>{this.props.saveValue('A', evt.target.value)}} />
但这也不起作用,因为单击Reset/Clear按钮时,虽然视图被重新渲染,但defaultValue
在创建视图后不会更新。
第三种方法:
因此,我最终添加了一个onChange
监听程序,但不执行任何操作。
<input type="url" value={this.props.values.A}
onChange={()=>{console.log('do nothing')}
onBlur={(evt)=>{this.props.saveValue('A', evt.target.value)}} />
同样,这不起作用,因为在调用onChange
之后重新呈现视图,并且由于props
中没有反映值,value
似乎在每次击键时都重置回初始。
第四种方法:
我上一次尝试是维护state
In组件并从状态读取值,并且每onChange
将值保存回状态。这在很大程度上是有效的,但只要道具有外部更改并重新呈现视图,state
就不会更新。因此,我添加了一个getDerivedStateFromProps
函数来查看:
static getDerivedStateFromProps(props, state) {
return props.values;
}
现在,这又不起作用了。原因是,即使我临时将值保存到STATE,并且在属性中将状态重置为初始值,也会调用此函数。
某个ReactJS专家可以帮助我解决我的用例吗?
解决方案
根据对Liren Yeo解决方案的评论,我将在componentDidUpdate
上处理道具-状态协调,其中您将获得旧的state
和props
。这样,您就可以确定this.props
是如何更新的,并采取相应的措施。当props
中的值与state
或oldProps
不匹配时,更新是外部的,您应该覆盖状态中未保存的更改。
代码应如下所示
componentDidUpdate(prevProps) {
if (this.props.values !== prevProps.values && this.props.values !== this.state.values) {
this.setState({values:this.props.values});
}
}
如果采用此方法,还可以保留输入uncontrolled
并通过引用更新其值。这解决了controlled
输入的一些不可靠性问题,例如,当您键入小数逗号时,type='number'
返回undefined
作为其值。您仍然需要存储onChange
值,但只需保存onBlur
并在componentDidUpdate
中处理状态属性对账
相关文章