1

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

4

2 回答 2

0

我认为你可以做到这一点。

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

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

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

于 2019-01-19T05:59:15.827 回答
0

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

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>

于 2019-01-20T20:07:32.320 回答