Как и большинство из вас, кто наткнулся на это, я нахожусь в процессе изучения React и фронтенд-разработки в целом. Хотя время от времени обучение может быть невероятно захватывающим, очень неприятно сталкиваться с препятствием на раннем этапе и чувствовать, что я не понимаю ключевой концепции. Часть меня хочет, чтобы поезд двигался и просто продолжал, но я знаю, что полное понимание фундаментальных знаний имеет решающее значение.

Я следил за «Полным руководством по React» Максимилиана Шварцмюллера на Udemy и обнаружил, что лучший способ справиться с некоторыми из сложных концепций — написать пошаговые руководства, разбитые как можно проще. Я делюсь ими в надежде, что есть хотя бы еще один идиот вроде меня, которому они могут быть полезны.

Мой первый серьезный учебный кризис произошел на уроке 59, лекции о подъеме состояния. Просматривая комментарии, я был не одинок. Что делало это таким трудным, так это то, что все эти части соединялись друг с другом, из-за чего было трудно отслеживать, что, куда и почему. В чем мой разум нуждался, так это в ясном виде ПРИКАЗА. И поэтому я написал это руководство, используя примеры курса Udemy.

ПЕРВАЯ ЧАСТЬ

Сохранение данных формы с помощью useState

На этом этапе мы работаем с формой и хотим сохранить любые данные, которые пользователь вводит в объект, чтобы затем мы могли отправить эти данные в родительский компонент во второй части.

Шаг 1

Работая в дочернем компоненте, выберите элемент HTML, из которого вы хотите собирать данные (например, поле ввода), и добавьте обработчик событий. Обработчики событий — это специальные атрибуты, начинающиеся с «on». В этом примере наш обработчик событий будет onChange.

<input type=”text” onChange={}>

Шаг 2

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

const titleChangedHandler = () => {};

Теперь самое главное, чтобы функция сохранялась в переменной и чтобы обработчик события, добавленный на первом шаге, указывал на эту функцию. Соглашение об именах состоит в том, чтобы заканчивать имя переменной на «Handler», поэтому мы назовем это titleChangedHandler.

<input type="text" onChange={titleChangedHandler};

Шаг 3

Следующим шагом является реализация хука useState. Во-первых, мне нужно import 'useState from 'react' , чтобы я мог использовать хук в этом компоненте.

Шаг 4

Затем, чтобы реализовать useState, я создаю константу, используя деструктурирование массива. Первая переменная — это наша «переменная состояния», и ее значение устанавливается в круглых скобках useState с другой стороны оператора присваивания. Итак, я объявляю переменную состояния и устанавливаю ее начальное значение (в данном случае пустую строку), я называю это enteredTitle.

const [enteredTitle, ] = useState("")

Вторая переменная в массиве — это функция, которая обновляет состояние. Стандартное соглашение об именах должно начинаться с «set». Здесь я назову его setEnteredTitle.

const [enteredTitle, setEnteredTitle] = useState("")

Шаг 5

Возвращаясь к функции стрелки, которую я сделал на втором шаге, я собираюсь использовать функцию setEnteredTitle внутри функции и присвоить ей новое значение.

Помещение ее внутри этой функции стрелки означает, что она будет обновлять onChange, потому что эта функция вызывается обработчиком событий onChange, который я поместил в качестве атрибута элемента ввода.

Итак, я возвращаюсь к пустой функции titleChangedHandler и заполняю ее.

const titleChangedHandler = (event) => {
  setEnteredTitle(event.target.value);
}; 

Любой параметр, который я добавляю в функцию стрелки, автоматически создает синтетический объект события, когда происходит изменение.

Внутри объекта события есть объект target, который показывает список пар ключ-значение, представляющих текущее состояние элементов DOM, в которых происходит изменение (ввод). Свойство value (внутри свойства target) содержит текущее значение ввода в момент времени, когда произошло событие (в данном примере onChange .

Шаг 6

Повторите эти шаги для всех элементов формы.

Шаг 7

Если на форме есть кнопка с type="submit", то на элемент form я могу добавить обработчик события onSubmit.

<form onSubmit={}>

Шаг 8

Затем я могу добавить функцию-обработчик, я назову ее submitHandler и пока оставлю пустой.

const submitHandler = () => {};

Шаг 9

Я возвращаюсь к элементу формы и указываю обработчику события onSubmit функцию-обработчик.

<form onSubmit={submitHandler}>

Шаг 10

Важно помнить, что поведение браузера по умолчанию при отправке формы заключается в обновлении страницы и отправке запроса на сервер (в данном случае на сервер разработки реагирования). Но то, что я хочу сделать здесь, это обработать отправку формы с помощью JavaScript и вручную использовать данные, которые я собрал из формы, без обновления apge.

Способ сделать это в React — получить доступ к синтетическому объекту события в функции submitHandler и использовать метод preventDefault(), который предотвращает отправку запроса, поэтому мы можем продолжать использовать JavaScript без перезагрузки страницы.

const submitHandler = (event) => {
  event.preventDefault();

Шаг 11

Теперь в функции submitHandler я хочу создать объект со всеми данными из формы на момент нажатия кнопки отправки, я назову его expenseData.

Это будет выглядеть так:

const submitHandler = (event) => {
  event.preventDefault();
  const expenseData = {
    title: enteredTitle,
    amount: enteredAmount,
    date: new Date(enteredDate),
  };
};

Итак, теперь у меня есть объект, который создается, когда пользователь нажимает кнопку «Отправить». Но я также хочу, чтобы форма очищалась, когда пользователь нажимает кнопку «Отправить». Как мне это сделать?

Шаг 12

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

<input type="text" value={enteredTitle} onChange={titleChangedHandler}>

Шаг 13

Теперь, когда я создал двустороннюю привязку между вводом и состоянием, я могу очистить поле ввода при отправке, вызвав setEnteredTitle() и установив его в пустую строку, тем самым очистив то, что ввел пользователь.

Это работает только в том случае, если к входным данным добавлен реквизит value, в противном случае входные данные не могут быть изменены. Итак, внутри функции submitHandler после объекта expenseData я вызову setEnteredTitle(""); и сделаю то же самое для других полей ввода.

const submitHandler = (event) => {
  event.preventDefault();
  const expenseData = {
    title: enteredTitle,
    amount: enteredAmount,
    date: new Date(enteredDate),
  };
  setEnteredTitle("");
  setEnteredAmount("");
  setEnteredDate("");
};

ЧАСТЬ ВТОРАЯ

Подъем данных

Хорошо, пока я построил состояние в своем дочернем компоненте, я также собрал данные и сохранил их в объекте, а также очистил поля ввода после нажатия кнопки отправки. Следующий шаг — перенести данные в родительский элемент, где я собираюсь их использовать.

Шаг 1

В родительском компоненте перейдите к return, где рендерится дочерний компонент, и добавьте новую опору. Я назову свойство onSaveExpenseData, чтобы было понятно, что значение свойства — это функция.

Шаг 2

Затем я делаю все как обычно и объявляю переменную-обработчик как стрелочную функцию. Я также передам ему аргумент enteredExpenseData, который я собираюсь использовать для сбора данных в дочернем компоненте.

const saveExpenseDataHandler = (enteredExpenseData) => {}

Шаг 3

Теперь, возвращаясь к дочернему компоненту, я должен использовать свойство onSaveExpenseData в качестве параметра. Поэтому первым шагом является указание функции ExpenseForm принять реквизиты.

const ExpenseForm = (props) => {

Шаг 4

Теперь на submitHandler я получаю доступ к props.onSaveExpenseData и выполняю его.

const submitHandler = (event) => {
  event.preventDefault();
  const expenseData = {
    title: enteredTitle,
    amount: enteredAmount,
    date: new Date(enteredDate),
  };
  props.onSaveExpenseData();
  setEnteredTitle("");
  setEnteredAmount("");
  setEnteredDate("");
};

Вот где происходит волшебство!!

Мы выполняем функцию, расположенную в родительском компоненте, потому что указатель на функцию передается дочернему компоненту свойством onSaveExpenseData.

Это очень важный шаблон!

Шаг 5

Когда я вызываю onSaveExpenseData в функции submitHandler, я могу передать объект expenseData (который я создал выше) в качестве аргумента.

props.onSaveExpenseData(expenseData);

Это дает мне expenseData в качестве аргумента в родительском компоненте в функции saveExpenseDataHandler.

Итак, в родительском компоненте:

const saveExpenseDataHandler = (enteredExpenseData) => {}

enteredExpenseData может называться как угодно, это всегда будет expenseData, которому я установил значение onSaveExpenseData в дочернем компоненте.

Имя реквизита onSaveExpenseData — это то, что я использовал в дочернем компоненте. Вот как я получаю к нему доступ и устанавливаю значение для любых данных, которые я хочу поднять. Когда я хочу вывести эту информацию и использовать ее в родительском компоненте, я использую функцию-обработчик, в данном случае saveExpenseDataHandler. В функции-обработчике я могу передать аргумент, который автоматически будет содержать данные, которые я только что установил в дочернем компоненте.

Заключение

Надеюсь, это было кому-то полезно. Выстроить эти шаги в логическом порядке было невероятно полезно для меня, и я не мог легко найти это через Google.

Я новичок в React и JS в целом, поэтому в этой статье наверняка будут какие-то семантические ошибки, если вы их заметите, пожалуйста, укажите на них в комментариях, чтобы я мог их исправить.

Продолжаем учиться.