React Hooks Form Handling: обновление состояния объекта с помощью нескольких строковых элементов и одного элемента массива - PullRequest
0 голосов
/ 30 марта 2020

Я изучаю React, используя хуки для создания приложения. Я следовал учебному пособию, однако я хотел бы внести в него некоторые изменения. У меня есть объект с несколькими строковыми элементами и одним элементом массива:

  const [recipe, setRecipe] = useState({
    title: '',
    description: '',
    ingredients: [],
    instructions: '',
    tags: 'none'
  }); 

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

    setRecipe({ ...recipe, [e.target.name]: e.target.value });
  }

Пример одного из полей ввода, которые были похожи.

          <input
            type='text'
            placeholder='Title'
            name='title'
            value={title}
            onChange={onChange}
          />

Теперь, когда я изменил один из элементов на массив, он больше не работает. Я пробовал несколько способов сделать это, например:

 const [test, setTest] = useState({
    ingredients: ['bread', 'milk', 'honey']
  });

 const [query, setQuery] = useState('');

  const updateQuery = e => {

    setQuery(e.target.value);
  };

  const addItem = e => {
    e.preventDefault();

    setTest(test => ({ ingredients: [...test.ingredients, query] }));
  };

return (

          <div>
            <button className='btn btn-light btn-block' onClick={addItem}>
              Add ingredient
            </button>
            <input
              type='text'
              placeholder='Description'
              name='ingredients'
              value={ingredients}
              onChange=(updateQuery)
            />
          </div>
          <div>
            {test.ingredients.map(data => (
              <ul key={data}>{data}</ul>
            ))}
          </div>

  );

Я изо всех сил пытаюсь найти решение.

Помощь будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 30 марта 2020

Код, который вы предоставили, нуждается в некотором форматировании (иначе: onChange={onChange} вместо onChange и ваше входное значение должно иметь query вместо ингредиентов)

Кроме того, вы не возвращали старое состояние, когда редактируя его.

Я добавил в ваше состояние не целочисленное поле массива

const [test, setTest] = React.useState({
    nonArray: 0,
    ingredients: ["bread", "milk", "honey"]
  });

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

const addItem = e => {
    e.preventDefault();
    setTest(old => ({ ...old, ingredients: [...old.ingredients, query] }));
    setQuery("");
  };

И, похоже, чтобы работать как шарм.

Пожалуйста, отметьте рабочие коды и поле , которое содержит в основном ваш код.

0 голосов
/ 30 марта 2020

Проблема с этой строкой: setTest(test => ({ ingredients: [...test.ingredients, query] })

При работе с компонентами класса реакции было бы неплохо установить состояние, не распространяя все предыдущее состояние, например this.setState({ ingredients: [...test.ingredients, query] }), поскольку внутренняя реакция уже объединяет ваши новый объект, который вы передаете в this.setState с предыдущим состоянием.

В ответных хуках React.useState не выполняет слияние, поэтому необходимо объединить предыдущее состояние, например setState(test => ({ ...test, ingredients: [...test.ingredients, query] }).

edit: Также вы объявили переменную test в верх вашего компонента. Я рекомендую переименовать аргумент test внутри setTest в другое.

0 голосов
/ 30 марта 2020

Как мне кажется, вам нужно использовать useCallback в addItem, updateQuery, например

const updateQuery = useCallback(e => {

    setQuery(e.target.value);
  },[]);

const addItem = useCallback(e => {
    e.preventDefault();

    setTest(test => ({ ingredients: [...test.ingredients, query] }));
  },[query]);

Это принцип перехвата, если вы хотите понять этот принцип, вы можете искать Principle of useCallback.

Если вы хотите узнать легкий путь, я могу сказать вам одну вещь. Когда компонент рендеринга addItem имеет запрос -> изменение состояния -> но запрос addItem не может измениться

...