输入onChange和React逻辑

时间:2019-01-19 05:48:09

标签: javascript reactjs react-props react-state

我是一名JavaScript爱好者,但我是一名新的React初学者。 我在理解React逻辑时遇到了一些麻烦,因此我举了一个简单的示例,一个带有数字输入和取消按钮的应用程序,用于取消上一个动作:

class App extends React.Component {    //A simple numeric input and a cancel button
  constructor(props){
    super(props);
    this.state={
      selectedNumber:0,
      lastNumber:null
    }
  }
  render() {
    return (
      <div className="App">
        <input type="number" value={this.state.selectedNumber} onChange={this.onNumberChange}></input>
        <button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
      </div>
    );
  }
  onNumberChange=(e)=>{
    let prevNumber=this.state.selectedNumber;
    this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
  }
  onUndo=(e)=>{
    let prevNumber=this.state.lastNumber;
    this.setState({selectedNumber:prevNumber,lastNumber:null});
  }
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div id="root">
  </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>

一切正常,但是假设用户输入数字200(通过键入),然后想要撤消该值并检索到最后一个,它将回落到20,因为每个键盘输入都会使用输入值刷新状态。 ..

为避免此行为,我尝试将输入移动到自定义组件中,向其添加本地状态,并根据组件属性呈现输入值。我在本地添加了一个onChange事件,该事件可以根据用户“实时”输入设置相应的组件状态,然后将一个onBlur事件绑定到父级的回调,该回调将其自身的状态相应地设置为“完整”用户条目。

该组件最初呈现良好,当您键入它时呈现良好,但是当通过“取消”按钮在外部进行更改时不会更新...

class App extends React.Component {    //A simple numeric input and a cancel button
  constructor(props){
    super(props);
    this.state={
      selectedNumber:0,
      lastNumber:null
    }
  }
  render() {
    return (
      <div className="App">
        <MyNumericInput selectedNumber={this.state.selectedNumber} onBlur={this.onBlur}/>
        <button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
      </div>
    );
  }
  onBlur=(e)=>{
    let prevNumber=this.state.selectedNumber;
    this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
  }
  onUndo=(e)=>{
    let prevNumber=this.state.lastNumber;
    this.setState({selectedNumber:prevNumber,lastNumber:null});
  }
}
class MyNumericInput extends React.Component {
  constructor(props){
    super(props);
    this.state={
      selectedNumber:props.selectedNumber
    }
  }
  render() {
  return(
    <input type="number" value={this.state.selectedNumber} onChange={this.onChange} onBlur={this.props.onBlur}/>);
  }
  onChange=(e)=>{
    this.setState({selectedNumber:e.target.value});
  }
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div id="root">
  </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>

2 个答案:

答案 0 :(得分:0)

我想你可以做到的。

onBlur = () => {
  this.setState(prevState => ({ lastNumber: prevState.selectedNumber }));
}

onChange = (e) => {
  this.setState({ selectedNumber: e.target.value });
}

现在,每当输入中焦点模糊时,您的lastNumber都会更新。并且在单击撤消按钮时,它应该可以正常工作。 我希望它能起作用。快乐的编码:)

答案 1 :(得分:0)

我已经在这个论坛上找到了解决方案...

stackoverflow.com/questions/53479598/reactjs-save-input-value-on-blur-and-not-on-every-key-stroke

BUT React文档指出这不是一个好习惯...

  

您可以在componentDidUpdate()中立即调用setState(),但是它也会引起额外的重新渲染,这虽然对用户不可见,但是会影响组件的性能。如果您要“镜像”来自上方的道具的某些状态,请考虑直接使用道具。

我将更新后的代码与上面的链接中提供的解决方案放在一起,您可以确认这种方法不好,还有什么替代方法?

class App extends React.Component {    //A simple numeric input and a cancel button
  constructor(props){
    super(props);
    this.state={
      selectedNumber:0,
      lastNumber:null
    }
  }
  render() {
    return (
      <div className="App">
        <MyNumericInput selectedNumber={this.state.selectedNumber} onBlur={this.onBlur}/>
        <button disabled={this.state.lastNumber===null} onClick={this.onUndo}>Undo last action</button>
      </div>
    );
  }
  onBlur=(e)=>{
    let prevNumber=this.state.selectedNumber;
    this.setState({selectedNumber:e.target.value, lastNumber:prevNumber});
  }
  onUndo=(e)=>{
    let prevNumber=this.state.lastNumber;
    this.setState({selectedNumber:prevNumber,lastNumber:null});
  }
}
class MyNumericInput extends React.Component {
  constructor(props){
    super(props);
    this.state={
      selectedNumber:props.selectedNumber
    }
  }
  render() {
  return(
    <input type="number" value={this.state.selectedNumber} onChange={this.onChange} onBlur={this.props.onBlur}/>);
  }
  onChange=(e)=>{
    this.setState({selectedNumber:e.target.value});
  }
  componentDidUpdate(prevProps) {
    if (this.props.selectedNumber !== prevProps.selectedNumber && this.props.selectedNumber !== this.state.selectedNumber) {
      this.setState({selectedNumber: this.props.selectedNumber});
    }
  }
}
ReactDOM.render(<App/>, document.getElementById('root'));
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div id="root">
  </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</body>
</html>