Реагируйте, устанавливая несколько входных данных в массиве объекта состояния

#reactjs #material-ui #frontend

Вопрос:

Я не уверен, что это возможно сделать, в моем приложении React у меня есть <form> следующие поля ввода:

 <TextField />
<TextField />
<TextField />
 

и у меня есть штат

 const [info, setInfo] = useState({
    firstName:"", 
    lastName:"",
    colors:[]
})
 

Я знаю , как установить одно поле с помощью ES6, например setInfo(...info, firstName:e.target.value) , но, похоже, это не работает с массивом в объекте.

В настоящее время, если я хочу установить цвета, я иду:

 <TextField onChange={addColor1}/>
<TextField onChange={addColor2}/>
<TextField onChange={addColor3}/>
 

и затем я создаю array colors = [color1, color2, color 3] , и, наконец, я ‘ SetInfo({…информация, цвета:цвета})

Но я хочу знать, есть ли способ задать цветовой массив без необходимости писать повторяющиеся функции, такие как addColor1 , addColor2

Спасибо!

Комментарии:

1. Есть ли какая-то конкретная причина, по которой вы хотите это сделать ?? Мне просто любопытно… Чтобы ответить на ваш вопрос, вы можете использовать «нажать»

2. Фактически нажатие на массив в состоянии приведет к его изменению. Вы можете распространить массив точно так же, как вы в настоящее время распространяете объект. setInfo({...info, colors:[...info.colors, colorToAdd]})

3. @NoxinDVictus говорят, что в будущем приложение будет расти, и люди захотят добавлять больше цветов, которые им нравятся, тогда должна быть кнопка, чтобы добавить больше полей ввода и позволить людям вводить больше цветов, решение в моем коде никогда не будет идеальным, я думаю

Ответ №1:

Это очень хороший вопрос. Давайте посмотрим, сможем ли мы его построить.

   const addColor = color => e => {
    const oldColors = info.colors
    // do whatever to create a new colors
    // based on oldColors and color, ex.
    const colors = [...oldColors, color]
    
    setInfo({ ...info, colors: colors })
  }
 

Вы должны уметь использовать его таким образом.

   <TextField onChange={addColor('red')} />
 

Это идея, color => e я думаю, что вы могли бы найти ее полезной. Но я точно не знаю, как вы справитесь со структурой массива. В конце концов, я не думаю, что ваш способ сработает, но просто продолжайте пытаться или ищите что-то под названием виджет MultiSelect Checkboxes или что-то в этом роде. Они больше используются для множества предметов.

Комментарии:

1. как я уже сказал, вам нужно посмотреть , что реализовано в TextField , возможно, вам это не нужно e , тогда вы можете отказаться от этого.

Ответ №2:

Да, вы определенно можете использовать одну функцию для обработки событий изменения для всех элементов управления формами.

Лучше изменить структуру данных цветов на объект или карту, но если вы хотите использовать массив, вот пример:

Редактировать красноречивый-pateu-lu2xo

 export default function App() {
  const [info, setInfo] = useState({
    firstName: "",
    lastName: "",
    colors: new Array(3).fill("")
  });

  const handleChange = ({ target: { name, value } }) => {
    setInfo((prevInfo) => {
      if (name === "firstName" || name === "lastName") {
        return { ...prevInfo, [name]: value };
      }

      // to get 0/1/2 from color0/color1/color2
      const colorIndex =  name[name.length - 1];

      return {
        ...prevInfo,
        colors: Object.assign([...prevInfo.colors], { [colorIndex]: value })
      };
    });
  };

  return (
    <div className="App">
      <input
        type="text"
        value={info.firstName}
        name="firstName"
        onChange={handleChange}
      />
      <input
        type="text"
        value={info.lastName}
        name="lastName"
        onChange={handleChange}
      />
      <div>
        {info.colors.map((color, index) => {
          return (
            <textarea
              key={index}
              value={color}
              name={`color${index}`}
              onChange={handleChange}
            />
          );
        })}
      </div>
      {JSON.stringify(info)}
    </div>
  );
}