Как я могу создать массив состояний в React с помощью крючков?

#javascript #reactjs #react-hooks

Вопрос:

У меня есть число n, которое может быть любым значением, и я хочу отобразить n полей ввода, отслеживая состояние каждого ввода, но мне трудно понять, как это сделать. Например, если n = 3, я хочу сделать что-то вроде этого:

 <div>
    <input onChange={(e) => setValue1(e.target.value)}/>
    <input onChange={(e) => setValue2(e.target.value)}/>
    <input onChange={(e) => setValue3(e.target.value)}/>
< /div> 

В этом примере мне нужно было бы вручную создать три состояния: value1, value2, value3. Моя цель-сделать его динамичным, поэтому, если в будущем я изменю n на 4 или любое другое число, мне не придется вручную создавать новые состояния и возиться с компонентом. Есть ли хороший способ сделать это с помощью крючков?

Ответ №1:

Вы должны создать состояние ввода, чтобы отслеживать каждый ввод:

 import React, { useState } from 'react';
import './style.css';

export default function App() {
  const [inputs, setInputs] = useState(Array(10).fill(''));
  const inputChangedHandler = (e, index) => {
    const inputsUpdated = inputs.map((input, i) => {
      if (i === index) {
        return e.target.value;
      } else {
        return input;
      }
    });
    setInputs(inputsUpdated);
  };
  return (
    <div>
      {inputs.map((input, i) => (
        <input onChange={e => inputChangedHandler(e, i)} value={input} />
      ))}
    </div>
  );
}
 

Вы можете проверить здесь, как все работает:
https://stackblitz.com/edit/react-sdzoqh

Ответ №2:

Вы можете создать новый массив с useState крючком размера num , который передается от его родителя, а затем использовать его индекс, т. Е. i вы можете изменить его входное значение с помощью setValue функции.

ДЕМО-ВЕРСИЯ CODESANDBOX

Просто для демонстрационной цели и заставьте input перейти на новую строку, в которую я ее завернул div .

 export default function App({ num }) {
  const [arr, setValue] = useState(Array(num).fill(""));
  console.log(arr);

  function onInputChange(index, event) {
    console.log(event.target.value);
    setValue((os) => {
      const temp = [...os];
      temp[index] = event.target.value;
      return temp;
    });
  }

  return (
    <div className="App">
      {arr.map((n, i) => {
        return (
          <div key={i}>
            <input onChange={(e) => onInputChange(i, e)} value={n} />
          </div>
        );
      })}
    </div>
  );
}
 

Ответ №3:

Может быть, я бы создал пользовательский крючок для создания своих входных данных, таких как

 import React, { useState } from "react";

const CreateInput = (n) => {
    const array = new Array(n).fill("");
    const [valueInput, setValueInput] = useState({});

    const handleChange = (event) => {
        const { name, value } = event.target;

        setValueInput({
            ...valueInput,
            [name]: value,
        });
    };

    const Input = array.map((_, i) => (
        <input key={i} name={i} onChange={handleChange} />
    ));

    return {
        Input,
    };
};

const Inputs = () => {
    const { Input } = CreateInput(3);

    console.log(Input);

    return <div>{Input}</div>;
};

export default Inputs;
 

Ответ №4:

Это можно было бы сделать с массивом в состоянии, со значениями во входных данных. Инициализировать пустыми строками

 const [values, setValues] = useState(Array(n).fill(""))
const handleChange = (e, i) => {
    const copy = values;
    copy[i] = e.target.value
    setValues(copy)
}
return (
    <div>
        {Array(n).map((x,i) => (
            <input value={values[i]} onChange={e => handleChange(e,i)} />
))}
    </div>
)

 

Ответ №5:

вы можете использовать useState([]) с массивом в качестве значения по умолчанию, например

импорт «./styles.css»; импорт React, { useState } из «react»;

 export default function App() {
  const n = 3;
  const [values, setValues] = useState(new Array(n).fill(1, 0, n));

  const handleChange = (i, value) => {
    const v = [...values];
    v[i] = value;
    setValues(v);
    
  };

  const inputsRendrer = (values) => {
    return values.map((v, i) => {
      return (
        <input
          key={i}
          value={values[i]}
          onChange={(event) => handleChange(i, event.target.value)}
        />
      );
    });
  };
  return <div className="App">{inputsRendrer(values)}</div>;
 

}

 new Array(n).fill(1, 0, n) // this create new array with values of 1 and length of n`