ReactJS: Save input value on blur and not on every key stroke

。_饼干妹妹 提交于 2019-12-06 21:45:33

Going by the comments on Liren Yeo's solution, I would handle the props-state reconciliation on componentDidUpdate, where you get both the old state and props. This way you can determine how this.props was updated and act accordingly. When the value in props does not match state nor oldProps, the update is external and you should override the unsaved changes in the state.

The code should look something like this

componentDidUpdate(prevProps) {

if (this.props.values !== prevProps.values && this.props.values !== this.state.values) {
  this.setState({values:this.props.values});
   }
}

If you go this route, you can also leave the input uncontrolled and update its value through a reference. This solves some unreliability with controlled inputs, like for example, a type='number' returning undefined as its value when you type a decimal comma. You still need to store the value onChange but only save it onBlur and handling the state-prop-dom reconciliation in componentDidUpdate

You will still need onChange to help you set the states of both url input. onBlur is only used to trigger saving, it's 2 different events for different purposes.

Since your A & B values are passed down from parent component. MyView's parent component should pass down this.state.values and the functions to set the state.

Refer to this snippet if everything is in single component. You should be able move handleChange function up to its parent component.

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>

EDIT: Your fourth approach should work with the following:

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

constructor(props) {
  super(props)
  this.state = {
    values: props.values
  }
}

so basically the this.state.values is the final source of truth. When user types something, you setState in this component and change it. But if props.values changes (from external source), getDerivedStateFromProps will update the values state.

So with the idea that onChange works, I would recommend you to take a look at this:

https://schier.co/blog/2014/12/08/wait-for-user-to-stop-typing-using-javascript.html Navigate to the heading: Wait for Typing to Stop

Hope it can somehow lead you to what you want to achieve.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!