ReactJS:将输入值保存在模糊上,而不是每个关键笔划上



我创建了一个React View,比如MyView,它有两个文本输入,其初始值将由从DB读取的父级传递。

我还希望将更改后的值保存回DB。因此,视图也被传递了一个相同的回调函数。

请考虑DB保存操作很重,不应该经常这样做。因此,我决定在输入框上侦听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侦听器,但作为no-op。

<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上将值保存回状态。这在很大程度上起到了作用,但每当道具发生外部更改并重新渲染视图时,state都不会更新。因此,我添加了一个getDerivedStateFromProps函数来查看:

static getDerivedStateFromProps(props, state) {
return props.values;
}

现在,这又不起作用了。原因是,即使我临时将值保存到state,并且状态在props中重置为初始值,也会调用此函数。

一些ReactJS专家能帮我做用例吗?

您仍然需要onChange来帮助设置两个url输入的状态。onBlur仅用于触发保存,它是两个不同的事件,用于不同的目的。

自从你的A&B值是从父组件传递下来的。MyView的父组件应该向下传递this.state.values和设置状态的函数。

如果所有内容都在单个组件中,请参阅此代码段。您应该能够将handleChange函数上移到其父组件。

class App extends React.Component {
state = {
values: {
A: '',
B: ''
}
}
handleChange = e => {
this.setState({
values: {
...this.state.values,
[e.target.name]: e.target.value
})
}
handleBlur = e => {
if (e.target.name === 'A') {
alert(`Saving A: ${this.state.values.A}`)
}
if (e.target.name === 'B') {
alert(`Saving B: ${this.state.values.B}`)
}
}
render() {
return (
<div>
<label>Value A</label>
<input
type="url"
name="A"
value={this.state.values.B}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
<label>Value B</label>
<input
type="url"
name="B"
value={this.state.values.A}
onChange={this.handleChange}
onBlur={this.handleBlur}
/>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
</div>


编辑:您的第四种方法应该使用以下方法:

static getDerivedStateFromProps(props, state) {
return { values: props.values }
}
constructor(props) {
super(props)
this.state = {
values: props.values
}
}

所以基本上CCD_ 25是真理的最终来源。当用户键入某个内容时,您可以在此组件中setState并对其进行更改。但如果props.values发生更改(来自外部源(,getDerivedStateFromProps将更新值状态。

根据对Liren Yeo解决方案的评论,我将在componentDidUpdate上处理道具状态对账,在那里您可以同时获得旧的stateprops。通过这种方式,您可以确定this.props是如何更新的,并采取相应的行动。当props中的值与stateoldProps不匹配时,更新是外部的,您应该覆盖状态中未保存的更改。

代码应该看起来像这个

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中处理状态道具dom对账

因此,考虑到onChange的有效性,我建议您看看这个:

https://schier.co/blog/2014/12/08/wait-for-user-to-stop-typing-using-javascript.html导航至标题:等待键入停止

希望它能以某种方式引导你实现你想要的目标。

相关内容

  • 没有找到相关文章

最新更新