Как добавить идентификатор и массив входов в мое состояние? - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь обновить свое состояние:

inputData: {
    id: '',
    inputArr: ['']
}

Из формы, которую я получаю из своего состояния, и я генерирую его следующим образом:

inner = arr.input.map((inputs, index) => (
    <li key={index} name={index} id={inputs.id}>
        <label>{inputs.inputLabel}</label>
        <input
            // value={inputs.inputValue}
            type={inputs.inputType}
            onChange={this.handleChangeInp}
        />
    </li>
))

Этобудет иметь несколько входов, поэтому я хочу добавить все их входы в массив по порядку, чтобы я мог извлечь его позже, но моя функция handleChange, похоже, не работает, все знают, почему (я не могу получить идентификатор, что япрохождение с событием, ни для обновления массива)?

handleChangeInp = e => {
    const id = e.target.id;
    console.log(`the id is ${id}`);
    const index = Number(e.target.name);
    const inputData = this.state.inputData.inputArr.map((ing, i) => {
        console.log(i);
        i == index ? e.target.value : ing;
    });
}

спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 22 сентября 2018

Я думаю, что решение простое.Вместо того, чтобы помещать атрибут id и name в элемент li, добавьте его к input.Это должно позволить вам получить name от e.target.

ОБНОВЛЕНО: Основано на дополнительном исследовании:

Событие Synthetic onChange в React не передает атрибут id.Вам нужно придумать другое решение.Если вам нужно сохранить как имя, так и индекс ввода в массиве, вы можете объединить их специальным символом и разделить их в обработчике событий.Оглядываясь назад на некоторые формы, которые я создал, я вижу, что мне было легко использовать символ канала |, поскольку он обычно не используется, но, тем не менее, я знаю, что это будет последний канал в моей строке.

Обновлен массив карт входов

inner = arr.input.map((inputs, index) => {
    console.log({inputs});
    return (
        <li key={index}>
            <label>{inputs.inputLabel}</label>
            <input
                name={inputs.id + "|" + index} 
                value={inputs.inputValue} /* try not commenting this out */
                type={inputs.inputType}
                onChange={this.handleChangeInp}
            />
        </li>
    )
});

Обновлен обработчик onChange

handleChangeInp = e => {
    const name = e.target.name.split("|");
    // index will be last element of array, pop it off
    const index = Number(name.pop());
    // join the name array back with the pipe character just in case it's used in the name 
    const id = name.join("|");
    console.log(`the id is ${id}`);
    console.log(`the index is ${index}`);
    const inputData = this.state.inputData.inputArr.map((ing, i) => {
        console.log(i);
        i == index ? e.target.value : ing;
    });
}
0 голосов
/ 23 сентября 2018

Первое обновление:

Правильные параметры для сгенерированных входов:

let inner = arr.input.map((inputs, index) => (
  <li key={index} >
    <label>{inputs.inputLabel}</label>
    <input
      id={index}
      name={inputs.id}
      // value={inputs.inputValue}
      type={inputs.inputType}
      onChange={this.handleChangeInp}
    />
  </li>
))

Таким образом, у нас будет id и name, доступных в событии, но структура глубокого состояния вынуждает нас написать вот что:

handleChangeInp = e => {
  const id = e.target.id;
  console.log(`the id is ${id}`);
  const index = Number(e.target.id);
  // deep state update
  const newInputArr = this.state.inputData.inputArr.map((ing, i) => {
    console.log(i, e.target.name);
    return (i == index) ? e.target.value : ing;
  });
  const newInputData = {...this.state.inputData, inputArr: newInputArr}
  this.setState({ inputData: newInputData }, ()=>{console.log(this.state.inputData)})
}

Это 'работает' ... , но у этого метода обновления состояния есть 2 проблемы / недостатки :

  1. значения хранятся в массиве по индексу - у нас есть только пары индекс-значение;

  2. вторая проблема более серьезна - он хранит только первое значение! Для использования карты («поиск») мы должны инициализировать массив для каждого индекса - в противном случае он не хранит значения.

Мой совет -используйте объект (карту) для хранения значений:

this.state = {
  inputData: {
    id: '',
    inputArr: {}
  }
};

и обработчик, подобный этому:

handleChangeInp = e => {
  const {name, value} = e.target;
  console.log(name, value);
  // deep state update
  const newInputArr = {...this.state.inputData.inputArr,[name]:value};
  const newInputData = {...this.state.inputData, inputArr: newInputArr}

  this.setState({ inputData: newInputData }, ()=>{console.log(this.state.inputData)})
}

Таким образом, у нас есть пары id-значение и только для «затронутых» полей.

Работающий пример .

Конечно значение для входных данных может быть прочитано из состояния (если определено):

value={this.state.inputData.inputArr[inputs.id] 
  ? this.state.inputData.inputArr[inputs.id] : ''}

// or
value={this.state.inputData.inputArr[inputs.id]===undefined ? '' 
  : this.state.inputData.inputArr[inputs.id] }
// f.e. when we're using type conversions 
// and numerical value `0` could be used as valid input
0 голосов
/ 22 сентября 2018

e.target будет ссылаться на элемент и для получения его реквизитов, таких как id, name и т. Д., Вам всем нужно иметь реквизиты на самом элементе.

Чтобы получить идентификатор, вынужно передать реквизиты id:

<input
  id={inputs.id}
  type={inputs.inputType}
  onChange={this.handleChangeInp}
/>

Теперь e.target.id получит идентификатор входных данных.Чтобы получить имя, сделайте то же самое, что и выше.

В этом примере e.target - это <input /> элемент.И чтобы получить его свойства, вам просто нужно добавить реквизит.

...