React:根据所选选项添加/更改文本输入框

3
我正在尝试根据所选选项显示新的文本输入框。我能够像下面这样做到,但无论我将新的选择选项更改为什么,旧值始终存在。
有什么更好的方法可以实现此目标吗?感谢任何建议。
class loadComponent extends React.Component {
    static propTypes = {
      ......
    };
    static defaultProps = {
     ....
    };
    constructor() {
     super();
     this.state = {
       value: ""
     };
    }
     state = {
      ...
     };

reset = (selected) => {
       this.setState({
        selectedInputName: selected.target[selected.target.selectedIndex].text,
        selectedInputId: selected.target.value
       });
};

makeTextInput = () => {
    return (
        <TextInput
            label={this.state.selectedInputName}
            placeholder={`Please enter ${this.state.selectedInputName} here!`}
            onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
            showClear
            value={this.state.value}
        />
    );
};
render() {
    let newInputText = '';
    if (this.state.selectedInputId !== '') {
        newInputText = this.makeTextInput();
    }
    return (
        <Select
            label="What would you like to search with?"
            options={this.props.searchOptions}
            onChange={selected => this.reset(selected)}
        />
        <div className="search margin_bottom_large">
            {newInputText}
    );

所以基本上当输入类型改变时,您想要清除用户当前的输入? - canaan seaton
@canaanseaton 是的,那正是我想要达到的目标。 - oyeesh
好的,下面是我的解决方案。做类似这样的事情将允许您在任何时候重置输入值,例如当输入类型改变时。 - canaan seaton
3个回答

3

makeTextInput 函数会创建一个新的对象,但从 react 的角度来看,它是同一个组件,因为 react 通过查看它们的 typekey 来区分它们。要使 react 重新创建一个元素,您必须更改其中一个值。

每次渲染时,此代码都会更改 NewInputText 元素的 type(因为 NewInputText 始终指向新函数):

reset = (selected) => {
       this.setState({
        selectedInputName: selected.target[selected.target.selectedIndex].text,
        selectedInputId: selected.target.value
       });
};

makeTextInput = () => {
    return (
        <TextInput
            label={this.state.selectedInputName}
            placeholder={`Please enter ${this.state.selectedInputName} here!`}
            onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
            showClear
        />
    );
};
render() {
    let NewInputText = () => '';
    if (this.state.selectedInputId !== '') {
        NewInputText = () => this.makeTextInput();
    }
    return (
        <Select
            label="What would you like to search with?"
            options={this.props.searchOptions}
            onChange={selected => this.reset(selected)}
        />
        <div className="search margin_bottom_large">
            <NewInputText />
    );

这段代码每次都给TextInput分配不同的键:

reset = (selected) => {
       this.setState({
        selectedInputName: selected.target[selected.target.selectedIndex].text,
        selectedInputId: selected.target.value
       });
};

makeTextInput = () => {
    return (
        <TextInput
            key={Math.random()}
            label={this.state.selectedInputName}
            placeholder={`Please enter ${this.state.selectedInputName} here!`}
            onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
            showClear
        />
    );
};
render() {
    let newInputText = '';
    if (this.state.selectedInputId !== '') {
        newInputText = this.makeTextInput();
    }
    return (
        <Select
            label="What would you like to search with?"
            options={this.props.searchOptions}
            onChange={selected => this.reset(selected)}
        />
        <div className="search margin_bottom_large">
            {newInputText}
    );

太棒了!你解决了我所有的困难。感谢你提供详细的解释。 - oyeesh
我该如何在函数式组件中实现这个? - Manasseh Codes

2

有更好的方法吗?

我认为在这种情况下使用受控组件设计模式会是理想的选择。

class SomeInput extends Component {
    constructor() {
        super();

        this.state = {
            value: "" //Keep value state here
        };
    }

    render() {
        /* Doing something like the following will allow you to clear
           the input value simply by doing the following..

           this.setState({ value: '' });
        */
        return (
            <Input
                type="text"
                onChange={e => this.setState({ value: e.target.value })} // set value state to entered text
                value={this.state.value} // set value of input to value piece of state
            />
        );
    }
}

这将使您完全访问当前输入值,因此可以通过执行以下操作this.setState({ value: '' })随时将其设置为任何值或清除它以进行任何事件。


使用构造函数时无法渲染,不确定原因。这里也没有使用表单。受控组件是否应该始终使用表单? - oyeesh
不,表单并不重要,它仅仅规定了控制被捕获在组件状态中的值并通过在输入框中使用该值进行渲染的方法。 - canaan seaton
你能否发布一下带有构造函数的代码,这样我就可以看出可能出了什么问题。 - canaan seaton

0

不知道你的代码的其余部分可能会有用,但你可以尝试:

makeTextInput = () => (
        <TextInput
          label={this.state.selectedInputName}
          placeholder={`Please enter ${this.state.selectedInputName} here!`}
          onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
          showClear
        />
      );

change = (event) => {
     this.setState({
       selectedInputName: event.target.value
     });
 }   

render() {
      return (
          <Select
            label="What would you like to search with?"
            options={this.props.searchOptions}
            onChange={this.change}
          />
          <div className="search margin_bottom_large">
          {this.makeTextInput()}
       );

你需要做的就是正确地设置setState。每次更改状态时,组件将重新渲染,这意味着makeTextInput方法将被触发。
编辑:
顺便说一句,在render方法中返回组件时使用getter是个好主意,例如:
get textInput() { 
    return (
       <TextInput
         label={this.state.selectedInputName}
         placeholder={`Please enter ${this.state.selectedInputName} here!`}
         onBlur={event => this.setState({[this.state.selectedInputId]: event.target.value})}
         showClear
       />
    );

}

然后在渲染方法中,只需使用{this.textInput}


我已经更新了上面的代码。我正在做你提到的事情。我能够更改标签。我的问题是,之前输入的值始终存在,即使选择的选项已更改。我正在尝试重置它,但迄今为止没有成功。 - oyeesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接