Состояние компонента React с использованием ловушки useState неожиданно сбрасывается между обновлениями дочерних компонентов - PullRequest
0 голосов
/ 28 мая 2020

У меня есть простой компонент React, который поддерживает массив людей в состоянии с помощью хука useState. Компонент позволяет добавлять новых людей с помощью простого компонента дочерней формы. Он не функционирует должным образом, поскольку массив состояний people кажется сбрасывается / возвращается к своему начальному значению между добавлениями из дочерней формы.

Структура компонентов приведена ниже:

Родительский компонент

Главный родительский компонент выглядит следующим образом. Он хранит массив people в состоянии. Он также передает функцию onPersonSaved компоненту PersonEditor. onPersonSaved вызывается при нажатии кнопки сохранения редактора (подробнее об этом позже) и просто добавляет (без изменения) нового человека в массив people

const Parent = () => {
  const [people, setPeople] = useState( [
    { id: 1, firstName: "John", lastName: "Smith" },
    { id: 2, firstName: "Peter", lastName: "Jones" },
    { id: 3, firstName: "Sally", lastName: "Wilson" },
  ]);

  const onPersonSaved = (person) => {
      setPeople([...people, person]);
    }

  const addNew = () => {
    onPersonSaved({ id: 4, title: "Jane", url: "Johnson" });
  };


  return (
    <div>
      <Button type="button" onClick={addNew} content="Add Jane" />
      <PersonEditor
        onSubmit={onPersonSaved}
        person={people[0]}
      />
    </div>
  );
};

export default Home;

Дочерняя форма

Дочерняя форма определена ниже. Это достаточно просто, и человек может редактировать его через свой person prop. Он сохраняется в состоянии и обновляется с использованием useEffect, если свойство person изменяется.

Он также использует настраиваемый обработчик useForm для поддержания состояний поля и запуска обратного вызова onPersonSaved. Для информации, Button и Input являются компонентами semanti c -ui-react.

const PERSON_INITIALVALUE = {
  id: null,
  firstName: "",
  lastName: ""
}

const PersonEditor = (props) => {
  const [person, setLink] = useState(PERSON_INITIALVALUE);

  const personForm = useForm(person, {
    submit: (values) => {
      if (props.onSubmit) {
        props.onSubmit(values);
        setLink(PERSON_INITIALVALUE);
      }
    },
  });

  useEffect(() => {
    if (props.person) {
      setLink({ ...props.person });
    }
  }, [props.person]);


  return (
    <Fragment>
          <Input
            type="text"
            name="firstName"
            value={personForm.values.firstName}
            onChange={(e, data) => personForm.setField("firstName", data.value)}
          />
          <Input
            type="text"
            name="lastName"
            value={personForm.values.lastName}
            onChange={(e, data) => personForm.setField("lastName", data.value)}
          />
          <Button
            type="button"
            primary
            content="Save Person"
            onClick={personForm.submit}
          />
        </Fragment>
  );
};

Перехватчик useForm

Это настраиваемый перехватчик, который обеспечивает очень простую функциональность обработки формы, а именно управление полями и метод отправки. Он принимает набор начальных значений (в данном случае объект человека) и объект параметров, который в данном случае является просто свойством / функцией submit.

const useForm = (initialValues, opts) => {

  const [options] = useState(opts);
  const [values, setValues] = useState({});

  useEffect(() => {
    if (initialValues) {
      setValues({ ...initialValues });
    }
  }, [initialValues]);

  const setField = (field, value) => {
    setValues({ ...values, [field]: value });
  };

  const submit = () => {
    options.submit(values);
  };


  return {
    setField,
    values,
    submit,
  };
};

export default useForm;

Проблема

Когда я добавляю нового человека через форму, он без проблем добавляет его в массив на вид . Однако, когда я добавляю еще одного человека, этот человек добавляется, но до того, как это произойдет, массив people, кажется, вернулся / сброшен до исходного начального значения.

Итак, при первом добавлении в массив входят три исходных человека плюс новый человек, добавленный через редактор. Следовательно, массив имеет вид [John, Peter, Sally, FIRST NEW PERSON]. При втором добавлении в массиве есть исходные три человека, но не осталось первого человека, но добавлено второе лицо. Массив выглядит так: [John, Peter, Sally, SECOND NEW PERSON]

Если я вызываю функцию onPersonSaved непосредственно из родительского компонента, нажав кнопку Add Jane, я могу добавлять Джейн столько раз, сколько захочу, и people Массив состояний ведет себя так, как ожидалось.

Почему при использовании формы и настраиваемой ловушки состояние не сохраняется и почему оно сбрасывается до своего начального значения?

...