Связываем компоненты вместе
На данный момент у нас имеются все компоненты, которые нам нужны, пришло время объединять их.
В этом уроке мы должны ответить на несколько вопросов:
Где хранить список?
Каким образом мы добавляем новые пункты?
Как отобразить несколько дел сразу?
Каким образом мы их удаляем?
В этом уроке присутствует повышенная концентрация JavaScript. Я постараюсь объяснить все сложные моменты, а глубже с теорией мы познакомимся в следующей главе.
Где хранить список?
У нас есть два компонента: первый (Field.jsx) добавляет новые элементы, второй (Item.jsx) отображает их и имеет возможность удалить. Так как компоненты не должны знать друг о друге, быть максимально изолированными, хранить данные мы будем в ближайшем общем предке, стало быть, TodoApp.jsx:
export function TodoApp() {
const [items, setItems] = useState([]);
...Каким образом мы добавляем новые пункты?
Нам нужен способ сообщить в главный компонент (TodoApp), что произошло нажатие кнопки добавления, и что Field хочет добавить новую запись в наш список. В Реакте это делается с помощью коллбеков. Коллбек (от англ. call back — "перезвони мне") — это функция, которая передается из родительского компонента в дочерний как параметр, которую дочерний компонент вызывает для того, чтобы сигнализировать родителю о том, что произошло какое-то действие. Давай посмотрим, как мы можем применить это в нашей ситуации.
Для начала добавим Field в TodoApp(не забудь импортировать его):
import { Field } from './field';
export function TodoApp() {
//...
return (
<div>
<Field />
</div>
);
}Создадим функцию, которая будет коллбеком и добавим ее к пропсам Field:
Перейдем в Field.jsx и пропишем этот коллбек как обработчик нажатия кнопки:
(некоторые куски кода были пропущены для краткости)
Что здесь происходит:
При нажатии кнопки вызывается
onButtonClickonButtonClickвызывает переданный "сверху"onAddи передает ему как первый аргумент значение поля ввода.
Вернемся в TodoApp.jsx и напишем код, который добавляет элемент в список:
Это сложная конструкция, давай разберем по частям:
Функция
addNewItemвызывается, когда мы нажимаем на кнопку добавления.newItem— новый элемент.Внутри неё мы изменяем значение
items, теперь оно равно[...items, newItem][...items, newItem]— это способ описать массив, который состоит из всех элементовitems, а такжеnewItem.
Как отобразить несколько элементов списка сразу
Теперь, когда у нас есть список, в который мы можем добавлять элементы, нам надо научиться их отображать. Компонент элемента списка, кстати, должен выглядеть примерно так:
Вернемся в TodoApp. У нас есть массив items, надо "сконвертировать" их в <Item name={...}/> (кстати, не забудь импорировать его) и добавить в дерево. В этом нам поможет функция map.
Представь, что у тебя есть фабрика с конвейером. Пустые бутылки проходят по конвейеру через аппарат, который наливает в них воду. На входе было 100 пустых бутылок, на выходе — 100 полных бутылок. Так вот твой массив — это бутылки на конвейере, а map — это аппарат.
mapвызывает функциюfс каждым элементом массива, над которым она была вызвана, и составляет новый массив из результатов выполнения функции.
В нашем случае есть массив строк, нужно из него сделать массив Item:
Теперь добавим наши элементы в компонент TodoApp:
Проверь в браузере, что элементы добавляются.
Дополнительная информация
React устроен таким образом, что он пытается произвести как можно меньше манипуляций с веб-страницей для достижения нужного результата. Недостатком этого метода является то, что он иногда "путает" элементы массива и не всегда знает, какой элемент документа соответствует какому элементу массива.
Для этого было придумано "магическое" свойство key. Правило простое:
Если у нас есть массив React-компонентов, то у каждого из них должен быть свой, уникальный внутри массива,
key.
Давай разберемся, как им пользоваться.
Мы говорили о том, что map вызывает функцию f с каждым элементом массива. Однако, map передает в f не один, а три аргумента:
Элемент массива
Порядковый номер (индекс) элемента
Сам массив.
Перепишем функцию createItem так, чтобы она использовала порядковый номер в качестве key:
Удаление элементов
В этой главе мы познакомимся с сестрой функции map — функцией filter.
filterвызывает функциюfс каждым элементом массива (а также его индексом и самим массивом), над которым она была вызвана, и составляет новый массив из тех элементов исходного массива, для которыхfвернулаtrue.
Пример: отфильтровать массив чисел таким образом, чтобы остались только положительные:
Мы хотим написать функцию, которая обновляет список items, удалив из него элемент с указанным индексом (removedIndex):
Что происходит: filter вызывает f c элементами массива, f в свою очередь, возвращает true для всех элементов, кроме removedIndex.
Мы теперь можем дать нашим Item возможность удалять себя:
А Item может запрашивать удаление себя по нажатию кнопки:
Проверь в браузере, что элементы добавляются и удаляются.
О, одна небольшая вещь для самостоятельной работы:
Подумай, как сделать так, что поле ввода очищается после нажатия кнопки добавления.
Подумай, как сделать так, чтобы нельзя было добавить пустые строки
Ответ — в конце следующей главы.
Last updated
Was this helpful?