ReactJS 清除来自父组件的输入

IT技术 javascript reactjs
2021-05-12 15:13:36

我正在教自己用一个超级简单的应用程序做出react,该应用程序要求用户输入 UI 中显示的单词。如果用户输入正确,应用程序会显示另一个单词,依此类推。

我几乎可以正常工作,除了一件事:正确输入单词后,我需要清除输入元素。我在这里看到了几个关于输入元素如何清除自身的答案,但我需要从包含它的组件中清除它,因为这是检查输入的地方......

// the app
class AppComponent extends React.Component {
    constructor() {
      super();
      this.state = {
        words: ['alpha', 'bravo', 'charlie'],
        index: 0
      };
    }
    renderWordsource() {
      const word = this.state.words[this.state.index];
      return <WordsourceComponent value={ word } />;
    }
    renderWordinput() {
      return <WordinputComponent id={1} onChange={ this.onChange.bind(this) }/>;
    }
    onChange(id, value) {
        const word = this.state.words[this.state.index];
        if (word == value) {
            alert('yes');
            var nextIndex = (this.state.index == this.state.words.count-1)? 0 : this.state.index+1;
            this.setState({ words:this.state.words, index:nextIndex });
        }
    }
    render() {
      return (
        <div className="index">
          <div>{this.renderWordsource()}</div>
          <div>{this.renderWordinput()}</div>
        </div>
      );
    }
}

// the input component
class WordinputComponent extends React.Component {
    constructor(props) {
        this.state = { text:''}
    }
    handleChange(event) {
      var text = event.target.value;
      this.props.onChange(this.props.id, text);
    }
    render() {
      return (
        <div className="wordinput-component">
          <input type="text" onChange={this.handleChange.bind(this)} />
        </div>
      );
    }
}

看到哪里说了alert('yes')吗?这就是我认为我应该清除 的地方value,但这没有任何意义,因为它是一个参数,而不是组件的真正状态。我应该让组件将自身传递给更改函数吗?也许那时我可以改变它的状态,但这在设计方面听起来是个坏主意。

3个回答

执行此操作的 2 种常见方法是通过父级中的状态控制值或使用 ref 清除值。添加了两者的示例

第一个是使用 ref 并在子组件中放置一个函数来清除第二个是使用父组件的状态和受控输入字段来清除它

class ParentComponent1 extends React.Component {
  state = {
    input2Value: ''
  }
  clearInput1() {
    this.input1.clear();
  }
  clearInput2() {
    this.setState({
      input2Value: ''
    });
  }
  handleInput2Change(evt) {
    this.setState({
      input2Value: evt.target.value
    });
  }
  render() {
    return (
      <div>
        <ChildComponent1 ref={input1 => this.input1 = input1}/>
        <button onClick={this.clearInput1.bind(this)}>Clear</button>
        <ChildComponent2 value={this.state.input2Value} onChange={this.handleInput2Change.bind(this)}/>
        <button onClick={this.clearInput2.bind(this)}>Clear</button>
      </div>
    );
  }
}

class ChildComponent1 extends React.Component {
  clear() {
    this.input.value = '';
  }
  render() {
    return (
      <input ref={input => this.input = input} />
    );
  }
}

class ChildComponent2 extends React.Component {
  render() {
    return (
      <input value={this.props.value} onChange={this.props.onChange} />
    );
  }
}

ReactDOM.render(<ParentComponent1 />, document.body);
<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>

我有一个类似的问题:我想清除包含多个字段的表单。

虽然@noveyak两个解决方案都运行良好,但我想分享一个不同的想法,这使我能够在父子之间划分责任:父知道何时清除表单,项目知道如何对此做出react, 不使用 refs。

这个想法是使用一个修订计数器,每次按下 Clear 时都会递增,并对子项中此计数器的变化做出react。

在下面的例子中,有三个非常简单的孩子对清除按钮做出react。

class ParentComponent extends React.Component {
  state = {revision: 0}
  clearInput = () => {
    this.setState((prev) => ({revision: prev.revision+1}))
  }
  render() {
    return (
      <div>
        <ChildComponent revision={this.state.revision}/>
        <ChildComponent revision={this.state.revision}/>
        <ChildComponent revision={this.state.revision}/>
        <button onClick={this.clearInput.bind(this)}>Clear</button>        
      </div>
    );
  }
}
class ChildComponent extends React.Component {
  state = {value: ''}
  componentWillReceiveProps(nextProps){
    if(this.props.revision != nextProps.revision){
      this.setState({value : ''});
    }
  }
  saveValue = (event) => {
    this.setState({value: event.target.value})
  }
  render() {
    return (
      <input value={this.state.value} onChange={this.saveValue} />
    );
  }
}
ReactDOM.render(<ParentComponent />, document.body);
<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>

编辑: 我刚刚偶然发现了这个带有密钥的漂亮简单的解决方案,它在精神上有些相似(你可以把父母的revision当作孩子的key

清除表单的非常非常简单的解决方案是key在要从子组件呈现表单的 div 中添加唯一的key={new Date().getTime()}

render(){

        return(
            <div className="form_first_step fields_black" key={new Date().getTime()}>
                <Form
                className="first_step">
                
                  // form fields coming from child component
                  <AddressInfo />
                
                
                </div>
              </Form>
          </div>
        )
    }