【发布时间】:2018-11-26 10:55:32
【问题描述】:
我创建了一个 React View,比如 MyView,它有 2 个文本输入,其初始值将由从数据库读取的父级传递。
我还希望将更改后的值保存回数据库。因此,视图也传递了相同的回调函数。
考虑到数据库保存操作很繁重,您不应该经常这样做。因此,我决定在输入框中收听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)}} />
但这在重置/清除按钮单击时也不起作用,虽然视图已重新渲染,但 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,并从状态中读取值,然后在每个onChange 上将值保存回状态。这在很大程度上是有效的,但是每当对 props 进行外部更改并且重新渲染视图时,state 不会更新。所以,我添加了一个getDerivedStateFromProps 函数来查看:
static getDerivedStateFromProps(props, state) {
return props.values;
}
现在,这又不起作用了。原因是即使我暂时将值保存到状态并且状态已重置为道具中的初始值,也会调用此函数。
ReactJS 专家可以帮我解决我的用例吗?
【问题讨论】:
-
作为第一个信息,onChange 是否有效?数据发生变化时是否将数据发送到数据库?
-
标签: javascript reactjs onblur react-props getderivedstatefromprops