Данные и алгоритм рендера
Автор конспекта: Арина Василевская
Существует два мира: данные и алгоритм
-
Мир данных (
state) — хранение информации, с которой работает приложение. Данные являются первичными. Данные, лежащие в основеstate, переменчивы, они меняются как живой организм.Stateпозволяет реализации быть интерактивной.Reactреагирует на изменения нашегоstate, и приложение перерисовывается. -
Мир алгоритмов (
render algoritm) — преобразование данных в интерфейс (JSX/React-элементы). Алгоритм зависит от данных, на их основании работает, и с ними взаимодействует.
Наша задача, как разработчиков быть архитектором данных и алгоритмов. Разработчик не может
думать только о данных, он также должен учитывать, как эти данные будут использоваться в алгоритме,
стремясь к удобству, понятности и эффективности с обеих сторон – как во frontend, так и в
backend:
- Адаптация алгоритма под данные: Если формат данных задан внешним источником (например,
backend), и его нельзя изменить, алгоритм должен быть подстроен под существующую структуру данных. - Адаптация данных под алгоритм: Если становится понятно, что алгоритм будет очень неудобный при
работе с входящими данными, разработчик может адаптировать структуру данных (например, полученную
с
backend) под ту, с которой удобно работатьfrontend, выполняя преобразования.
Структура данных и алгоритм отрисовки
Для задачи отрисовки списка треков идеально подходящей структурой данных является массив
объектов, где каждый объект описывает наш трек. Этот массив выделяется в переменную и
называется состоянием (state), от которого зависит отрисовка.

Такая структура позволяет алгоритму итерироваться по каждому треку в массиве и на его основании
формировать соответствущий JSX-элемент. На основе каждого объекта создается элемент списка
(<li>), внутри которого есть заголовок(<div>) и трек(<audio>)
Обработка разных состояний данных
Выделим три состояния:
1. Нет данных

При пустом массиве в state на странице должно отобразится сообщение: 'Нет треков'. Это
реализуется с помощью раннего возврата(early return) из компонента:
2. Загрузка данных
Когда данные загружаются с сервера, важно различать два разных состояния:
- Данных точно нет → получен пустой массив.
- Данные ещё не получены → запрос в процессе, и результат неизвестен.
В ситуации ожидания неправильно показывать пользователю, что данных нет. Корректнее отобразить,
что приложение загружает информацию — например, вывести Loader. Это даёт пользователю понять, что
идёт процесс получения данных, а не ошибка или пустой результат.

В нашем случае, чтобы при загрузке не показывалось сообщение No tracks, используется промежуточное
состояние null для переменной tracks.
-
Если
tracks === null, это значит, что данные ещё не инициализированы и приложение находится в процессе их получения. В таком случае рендер должен вывестиLoading... -
Такая логика реализуется также через
early return: добавляется условиеif (tracks === null), при котором возвращаетсяLoading....
3. Интерактивность: выделение трека
Когда на экране что-то изменяется (элемент подсветился, исчез или появился), разработчику важно определить: какие данные должны меняться и как именно, чтобы алгоритм отрисовки мог корректно это отразить.

Сделаем подсветку определенного трека двумя способами.
Вариант 1
В каждый объект трека добавляется булевое поле isSelected: true/false. Алгоритм рендеринга
проверяет это свойство и применяет, например, CSS-стиль выделения(добавляем border выбранному
элементу). Проверяем наличие свойства в объекте с помощью тернарного выражения.
Тернарный оператор — это краткая форма записи условного выражения if...else, позволяющая выполнить одно из двух
действий в зависимости от истинности условия. Если условие верно, то выполняется выражение слева от :, если
ложно, то выполняется правое от : выражение.

✅ Плюсы: просто, если с backend данные уже приходят с этим флагом.
❌ Минусы:
- Возможна несогласованность (например, выделено несколько треков, хотя должен быть один).
- Засоряет данные
frontend-логикой, которая необходима только дляUI.
Вариант 2
Можно создать отдельную переменную selectedTrackId, в которой будет храниться id выбранного
трека или null, если ничего не выбрано. Алгоритм проходит по списку треков и для каждого
сравнивает track.id === selectedTrackId. Если совпадает — применяется стиль выделения. Если
selectedTrackId=== null → выделений нет:
✅ Преимущества:
-
Нормализация: данные треков остаются «чистыми», логика выделения вынесена отдельно.
-
Согласованность: изменения в одном месте, без риска забыть обновить данные в разных структурах.
-
Гибкость: удобно управлять выделением, даже если сервер не предоставляет эту информацию.
Итог занятия
✔️ Основная идея заключается в том, что данные всегда являются фундаментом, но их проектирование должно идти в связке с алгоритмом.
✔️ При разработке важно уметь различать разные состояния приложения: момент загрузки, ситуацию с пустым списком и работу с уже загруженными элементами.
✔️ Для интерактивности предпочтительно хранить отдельные переменные (например, ID), а не добавлять лишние поля в сами данные.
✔️ Согласованность состояния — ключ к правильной и предсказуемой работе интерфейса.
🏠 Домашнее задание
Алгоритмы и структуры данных в React
Цель задания
Закрепить понимание взаимосвязи между структурами данных и алгоритмами рендера в React на примере
создания интерактивного каталога товаров.
Задание 1
Базовая структура данных и алгоритм рендера
Создайте новый React-проект с помощью Vite либо можете продолжать работу в проекте из предыдущих
домашних заданий.
В App.tsx, отрисуйте список задач
Итоговый результат 🚀

Задание 2
Отображение состояний загрузки
Напишите алгоритм, который будет соответствовать следующим условиям:
- Если
tasks = null→ показать "Загрузка..."

- Если
tasks = []→ показать "Задачи отсутствуют"

- Если массив содержит таски → отрендерить список

Задание 3
Статус выполнения задачи
В зависимости от свойства isDone добавьте стили для заголовка задачи.
- Если задача выполнена, тогда необходимо зачеркнуть заголовок задачи.
textDecorationLine: line-through - Если задача не выполнена, тогда оставляем как есть.
textDecorationLine: none
Итоговый результат 🚀

Задание 4
Приоритет таски
В массиве сейчас 3 задачи. Но у каждой из задач может быть разный приоритет выполнения. Поэтому
расширим данные свойством priority.
- 0 - Низкий приоритет
- 1 - Средний приоритет
- 2 - Высокий приоритет
- 3 - Срочный приоритет
- 4 - Наивысший приоритет
Чтобы пользователь видел задачи с высоким приоритетом (2,3,4) добавьте свойство priority в каждую
таску и измените background для данных задач на оранжевый
Итоговый результат 🚀

Задание 5 ⭐
⭐ Дополнительное задание со звездочкой. Проделывать по желанию.
Для каждой задачи сделайте свой цвет.
- 0 - Низкий приоритет (
#ffffff) - 1 - Средний приоритет (
#ffd7b5) - 2 - Высокий приоритет (
#ffb38a) - 3 - Срочный приоритет (
#ff9248) - 4 - Наивысший приоритет (
#ff6700)
Доработайте код таким образом, чтобы цвет фона менялся в зависимости от приоритета задачи.
Итоговый результат 🚀

Совет: Если что-то кажется сложным, не переживайте! Это нормально на начальном этапе. Главное
— это практика и постепенное понимание концепций React.


