【问题标题】:Input onChange and React logic输入 onChange 和 React 逻辑
【发布时间】:2019-06-13 08:04:02
【问题描述】:

我是 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>

【问题讨论】:

    标签: javascript reactjs react-props react-state


    【解决方案1】:

    我认为你可以做到。

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

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

    【讨论】:

    • 我尝试了你的代码,但取消按钮不再起作用...... Ps:我编辑了上面的sn-p,所以它现在可以测试了
    【解决方案2】:

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

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

    但是 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>

    【讨论】:

      猜你喜欢
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2020-09-05
      • 2022-08-16
      • 1970-01-01
      • 2022-11-19
      相关资源
      最近更新 更多