ReactJS:在模糊时保存输入值,而不是在每次击键时保存输入值

laz*_*vab 5 javascript onblur reactjs react-props getderivedstatefromprops

我创建了一个 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>
        );
     }
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为React强制受控输入(带有value属性)始终伴随onChange侦听器。

第二种方法:

因此,我尝试将这些输入设为uncontrolled. 也就是说,value使用 代替属性defaultValue

<input type="url" defaultValue={this.props.values.A}
       onBlur={(evt)=>{this.props.saveValue('A', evt.target.value)}} />
Run Code Online (Sandbox Code Playgroud)

但这也不起作用,因为单击重置/清除按钮时,尽管视图已重新渲染,但defaultValue创建视图后不会更新。

第三种方法:

所以,我最终添加了一个onChange侦听器,但作为无操作。

<input type="url" value={this.props.values.A}
       onChange={()=>{console.log('do nothing')}
       onBlur={(evt)=>{this.props.saveValue('A', evt.target.value)}} />
Run Code Online (Sandbox Code Playgroud)

同样,这不起作用,因为视图在调用后重新渲染onChange,并且由于值尚​​未反映propsvalue似乎在每次击键时重置回初始值。

第四种方法:

最后我尝试的是维护一个state组件并从状态读取值,然后每次onChange将值保存回状态。这在很大程度上有效,但每当道具发生外部更改并且视图重新渲染时,state就不会更新。所以,我添加了一个getDerivedStateFromProps查看功能:

static getDerivedStateFromProps(props, state) {
    return props.values;
}
Run Code Online (Sandbox Code Playgroud)

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

一些 ReactJS 专家可以帮助我解决我的用例吗?

Die*_*osi 1

根据对 Liren Yeo 解决方案的评论,我将处理 的 props-state 协调componentDidUpdate,您可以在其中获得旧的stateprops. 这样您就可以确定this.props更新方式并采取相应措施。当值在propsstatenor不匹配时oldProps,更新是外部的,您应该覆盖状态中未保存的更改。

代码应该是这样的

componentDidUpdate(prevProps) {

if (this.props.values !== prevProps.values && this.props.values !== this.state.values) {
  this.setState({values:this.props.values});
   }
}
Run Code Online (Sandbox Code Playgroud)

如果您走这条路,您还可以保留输入uncontrolled并通过引用更新其值。这解决了controlled输入的一些不可靠性问题,例如,当您键入小数逗号时type='number'返回其值。undefined您仍然需要存储该值onChange,但只需保存它onBlur并处理 state-prop-dom 协调componentDidUpdate