【问题标题】:Dynamically create an array of inputs in React在 React 中动态创建输入数组
【发布时间】:2018-09-14 11:33:56
【问题描述】:

我还是 React 框架的新手。我正在开发一个项目,我希望允许用户创建选择字段。我目前正在使用 react-select 来呈现选择字段或下拉菜单。我需要他们从选择输入字段中选择的值。问题是用户需要能够创建多个输入字段。每个输入字段必须有一个唯一的键。我希望能够在他们选择它们时检索这些值。

以下是我目前所拥有的:

 class OptionsComponent extends React.Component{
  constructor(props){
   super(props);
   this.state = {
    fields: [],
    parentArray: [],
    optionsArray: [],
    selectedOption:'',

   };

this.handleSelect = this.handleSelect.bind(this); 
}

 handleSelect = (event, index) => {
  console.log(event);
  console.log(optionsArray);
  console.log(selectedOption);
  const optionsArray = [...this.state.optionsArray];
  let selectedOption = event.label;
  optionsArray[index]= event.target.value;

  this.setState({
    optionsArray,
    selectedOption: event.label,
  })}

 render(){

return(

  <div className="">
    <div className="optionsArea">

      { this.state.parentArray.map((el, index) =>
        <div key={index} className="selectDropdown ">
            { this.state.optionsArray.map((el, index) => {
              return <Select
              key={index}
              name="optionsSelect"
              className="userOptionSelectDropdown"
              placeholder="Select Variable"
              value={this.state.selectedOption}
              onChange={(event) => this.handleSelect(event)}
              onSelect={(event) => this.handleSelect(event)}
              options={this.state.fields.map((field, index) => {
              return {value: index, label: field.name;
            })} />
          })}
        </div>
      )
    }
    </div>

  </div>

    );
   }
 }

如果这是重复的,我提前道歉。我检查了类似的问题并进行了谷歌搜索,但我找不到任何东西。现在,当我在组件中使用此代码时,它不会呈现任何内容。我不太确定为什么。感谢您的帮助。

【问题讨论】:

    标签: reactjs react-select


    【解决方案1】:

    您可以设置组件的名称并在您的 handleSelect 期间获取它并直接获取值(例如,如果您使用引导程序 4 中的自定义控件,则可以使用)。请记住在选项中为索引使用不同的名称。

    handleSelect = (event) => {
        let name = event.target.name;
        let value = event.target.value; 
    
        // perform action
    
        ...
    
    }
    

    然后在您的渲染中生成地图中的唯一名称,例如 name={"optionsSelect_" + el + "_" + index} 或任何您喜欢的名称:

    ...
    
    { this.state.parentArray.map((el, index) =>
        <div key={index} className="selectDropdown ">
            { this.state.optionsArray.map((el, index) => {
              return <Select
              key={index}
              name={"optionsSelect_" + el + "_" + index}
              className="userOptionSelectDropdown"
              placeholder="Select Variable"
              value={this.state.selectedOption}
              onChange={(event) => this.handleSelect(event)}
              onSelect={(event) => this.handleSelect(event)}
              options={this.state.fields.map((field, index2) => {
              return {value: index2, label: field.name;
            })} />
          })}
        </div>
      )
    }
    
    ...
    

    如果设置名称不起作用,您也可以尝试引用:

    ...
    
    { this.state.parentArray.map((el, index) =>
        <div key={index} className="selectDropdown ">
            { this.state.optionsArray.map((el, index) => {
              return <Select
              key={index}
              ref={a => (this["optionsSelect_" + el + "_" + index] = a)}
              name={"optionsSelect_" + el + "_" + index}
              className="userOptionSelectDropdown"
              placeholder="Select Variable"
              value={this.state.selectedOption}
              onChange={(event) => this.handleSelect(event)}
              onSelect={(event) => this.handleSelect(event)}
              options={this.state.fields.map((field, index2) => {
              return {value: index2, label: field.name;
            })} />
          })}
        </div>
      )
    }
    ...
    

    然后将其放入您的句柄中(您将获得完整的组件):

    handleSelect = (event) => {
        let name = event.target.name;
        let element = this[name]; 
    
        // perform action
    
        ...
    
    }
    

    使用纯javascript获取选中值的方法有很多,看看here

    这很重要!

    如果您需要根据之前的状态修改状态,请不要这样做:

        ...
        const optionsArray = [...this.state.optionsArray];
        let selectedOption = event.label;
        optionsArray[index]= event.target.value;
    
        this.setState({
            optionsArray,
            selectedOption: event.label,
        })
        ...
    

    setState 还接收一个函数,并为您提供之前的状态以供您处理,进行所需的任何更改,并确保它们将被正确设置。

        ...    
        this.setState(prevState => {
            // get current state
            let newOptionsArray = prevState.optionsArray;
            let selectedOption = event.label; // or whatever
            newOptionsArray[index]= event.target.value; // or whatever
    
            return({
                optionsArray: newOptionsArray,
                selectedOption: event.label,
            });
        });
        ...
    

    阅读 in the official docs 以了解 setState 的工作原理。

    【讨论】:

    • 裁判是否被认为是不好的做法?我以为我读到裁判应该被认为是最后的手段。或者它们可以在 React 中使用吗?
    • 如果可以避免它们,最好使用替代方法,但如果没有替代方法,请使用它们。对于这种情况,我总是使用句柄方法,并使用句柄获取名称和值,并使用这些更新状态。
    【解决方案2】:

    不确定我是否完全理解您的要求/尝试做什么,但我相信这会做到:

    1. 使用选项初始化 Select 字段
    2. 使用来自用户输入的选项创建一个新的 Select 字段
    3. 每个字段都存储选定的选项(如果选择了一个)
    4. 点击“提交表单”会显示所有选择的选项

    工作示例:https://codesandbox.io/s/81jlqp31p9

    import each from "lodash/each";
    import map from "lodash/map";
    import isEmpty from "lodash/isEmpty";
    import React, { Component, Fragment } from "react";
    import Select from "react-select";
    
    export default class DynamicSelect extends Component {
      state = {
        Fields: [
          {
            name: "Field0",
            options: [
              { value: "chocolate", label: "Chocolate" },
              { value: "strawberry", label: "Strawberry" },
              { value: "vanilla", label: "Vanilla" }
            ]
          }
        ],
        selectedOptions: {}
      };
    
      clearSelections = () => this.setState({ selectedOptions: [] });
    
      handleChange = (name, value) => {
        this.setState(prevState => ({
          selectedOptions: [
            ...this.state.selectedOptions,
            {
              name: value
            }
          ]
        }));
      };
    
      handleAddField = () => {
        this.setState(prevState => {
          const { newFields } = this.state;
          if (!newFields) return;
          const arr = newFields.split(",");
          const options = map(arr, val => ({ value: val, label: val }));
    
          return {
            newFields: "",
            Fields: [
              ...this.state.Fields,
              {
                name: `Field${this.state.Fields.length}`,
                options
              }
            ]
          };
        });
      };
    
      handleFieldChange = e => {
        this.setState({ newFields: e.target.value });
      };
    
      showSelectedOptions = selectedOptions => {
        return map(selectedOptions, ({ name }) => name + "");
      };
    
      handleSubmit = e => {
        e.preventDefault();
    
        const { selectedOptions } = this.state;
    
        alert(`Selection option(s): ${this.showSelectedOptions(selectedOptions)}`);
      };
    
      render() {
        const { Fields, newFields, selectedOptions } = this.state;
    
        return (
          <form onSubmit={this.handleSubmit} style={{ margin: 20 }}>
            <h3 style={{ textAlign: "center" }}>Dynamic Select Fields</h3>
            {!isEmpty(Fields) &&
              map(Fields, ({ name, options }, key) => (
                <div key={key} style={{ marginBottom: 20 }}>
                  <div>{name}:</div>
                  <Select
                    name={name}
                    value={selectedOptions[name]}
                    onChange={({ value }) => this.handleChange(name, value)}
                    options={options}
                    style={{ marginBottom: 20 }}
                  />
                </div>
              ))}
            <div style={{ marginTop: 20 }}>
              <input
                style={{ marginBottom: 5, width: "100%" }}
                type="text"
                className="uk-input"
                onChange={this.handleFieldChange}
                placeholder="Create a Select Field (option, option, option, ..etc)"
                value={newFields}
              />
              <br />
              <button
                onClick={this.handleAddField}
                className="uk-button uk-button-default"
                type="button"
                disabled={newFields ? false : true}
              >
                Add Field
              </button>
            </div>
            <div style={{ marginTop: 40 }}>
              <button
                className="uk-button uk-button-primary"
                type="submit"
                disabled={!isEmpty(selectedOptions) ? false : true}
              >
                Submit Form
              </button>
            </div>
          </form>
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多