Кастомный React хук для изменения темы веб-приложения
2 года назад·2 мин. на чтение
Пишем кастомный React хук useTheme, который динамически меняет тему веб-приложения с помощью CSS переменных.
В этой статье напишем кастомный хук на ReactJS, который будет менять тему веб-приложения.
Особенности хука useTheme, который мы реализуем:
Код хука
Сам хук выглядит довольно просто.
Использование хука
Здесь добавлены две кнопки, каждая из которых отвечает за переключение на светлую или темную тему. Они обернуты в
- использует CSS переменные
- быстро кастомизируется
- плавный переход между темами
- умеет сохранять выбранную тему в local storage
Код хука useTheme
Сам хук выглядит довольно просто.
// hooks/use-theme.js import { useLayoutEffect, useState } from 'react' const isDarkTheme = window?.matchMedia('(prefers-color-scheme: dark)').matches const defaultTheme = isDarkTheme ? 'dark' : 'light' export const useTheme = () => { const [theme, setTheme] = useState( localStorage.getItem('app-theme') || defaultTheme ) useLayoutEffect(() => { document.documentElement.setAttribute('data-theme', theme) localStorage.setItem('app-theme', theme) }, [theme]) return { theme, setTheme } }
prefers-color-scheme
используется для определения выбранной пользователем темы (светлая или темная). Пользователь указывает свои предпочтения через настройку операционной системы или через настройку user agent.
document.documentElement.setAttribute('data-theme', theme)
- этой строчкой мы добавляем кастомный data-атрибут в тег html
. Таким образом, например, при выборе светлой темы в теге html
появится data-атрибут data-theme="light"
.
Добавление CSS переменных
Далее мы должны указать CSS переменные, которые будут иметь различные значение для разных тем. Например,--button-text-color
имеет значение #ffffff
при темной теме и #252525
- при светлой.
/* index.css */ html[data-theme='dark'] { --button-text-color: #ffffff; --button-background-color: #4e005c; --button-border-color: #ba8fc2; --background-color: #292929; --icon-color: #ba8fc2; } html[data-theme='light'] { --button-text-color: #252525; --button-background-color: #f9d4ff; --button-border-color: #4e005c; --background-color: #dfdfdf; --icon-color: #4e005c; }
Применение CSS переменных
Далее нам нужно применить эти CSS переменные к соответствующим элементам. Добавлениеtransition
дает плавность при переключении тем.
/* App.css */ .app__container { background-color: var(--background-color); transition: background-color 200ms linear; } .app__logo { color: var(--icon-color); transition: color 500ms linear; } .app__button, .app__button:hover, .app__button:focus, .app__button:active, .app__button:not(:disabled):not(.disabled):active { color: var(--button-text-color); background-color: var(--button-background-color); border-color: var(--button-border-color); transition: color 500ms linear, background-color 500ms linear, border-color 500ms linear; }
Использование хука useTheme
Здесь добавлены две кнопки, каждая из которых отвечает за переключение на светлую или темную тему. Они обернуты в ButtonGroup
.
Элементы логотип, контейнер и кнопка имеют соответствующие CSS классы, которые мы описали выше - app__logo
, app__container
и app__button
. В этих классах были использованы CSS переменные.
Исходный кодimport React from 'react' import Button from 'react-bootstrap/Button' import ButtonGroup from 'react-bootstrap/ButtonGroup' import { FaCoffee } from 'react-icons/fa' import { useTheme } from './hooks/use-theme' import './App.css' export default function App() { const { theme, setTheme } = useTheme() const handleLightThemeClick = () => { setTheme('light') } const handleDarkThemeClick = () => { setTheme('dark') } return ( <div className="app__container w-100 h-100 d-flex flex-column"> <div className="p-3 d-flex justify-content-end"> <ButtonGroup aria-label="Theme toggle"> <Button variant="secondary" onClick={handleLightThemeClick}> Light </Button> <Button variant="secondary" onClick={handleDarkThemeClick}> Dark </Button> </ButtonGroup> </div> <div className="flex-grow-1 d-flex flex-column justify-content-center align-items-center"> <FaCoffee size={100} className="app__logo mb-5" /> <div className="d-flex"> <Button className="app__button" type="button"> Subscribe </Button> </div> </div> </div> ) }
Полное руководство по React
2 года назад·3 мин. на чтение
Это руководство поможет плавно войти в Реакт разработку и понять как использовать react.
Мы начнем с самых базовых концепций. Рассмотрим различные варианты добавления ReactJS на сайт и создания React проекта. Создадим первые компоненты и шаг за шагом будем подробно рассматривать все части компонента - JSX, события, стили, хуки и т.д. Данный react туториал на русском разделен на удобные части, каждая из которых включает подробное объяснение и простые примеры. Этот гайд подойдет и для начинающих react разработчиков.
Также весь API собран в удобный справочник, в котором можно найти подробное объяснение конкретных функций React.
Установка
В этом разделе полного руководства по Реакт собраны все варианты установки React. Можно создать проект на React с нуля или постепенно внедрять его в существующее приложение. Также узнаем как настроить базовый набор инструментов на компьютере для разработки и отладки React приложения.- Как начать работать с React
- Как добавить React на сайт
- Настройка редактора IDE для работы с React
- Инструменты разработчика React
- Быстрый старт с React
- Мышление в стиле React
Интерфейс пользователя
В этой части руководства по React мы напишем первый React компонент. React компоненты - это переиспользуемые элементы пользовательского интерфейса. В приложении React каждая часть пользовательского интерфейса является компонентом.- Пишем первый React компонент
- Импорт и экспорт компонентов
- Разметка с JSX
- JavaScript в фигурных скобках в JSX
- Как передать пропсы компоненту
- Рендеринг по условию
- Рендеринг списков
- Чистые компоненты
Добавление интерактивности
Эта часть руководства по React посвящена тому как обрабатывать действия пользователя. Некоторые элементы на экране обновляются в ответ на действия пользователя. Например, клик по галерее изображений переключает активное изображение. В React данные, которые меняются со временем, называются состоянием. Вы можете добавить состояние к любому компоненту и обновить его по мере необходимости. В этой части курса по Реакт вы узнаете, как писать компоненты, которые обрабатывают взаимодействия, обновляют свое состояние и отображают разные выходные данные с течением времени.- Реакция на события
- Состояние - память компонента
- Рендеринг и фиксация
- Состояние как снимок
- Очередь обновлений состояния
- Обновление объектов в состоянии
- Обновление массивов в состоянии
Управление состоянием
Данная часть react js руководства включает подробное объяснение работы с состоянием. По мере роста вашего React приложения полезно более внимательно относиться к тому, как организовано состояние и как данные передаются между вашими компонентами. Избыточное или повторяющееся состояние является распространенным источником ошибок. В этой части вы узнаете, как правильно структурировать состояние, как поддерживать логику обновления состояния и как обмениваться состоянием между компонентами.- Реакция на ввод с состоянием
- Какую структуру состояния выбрать
- Обмен данными между компонентами
- Сохранение и сброс состояния
- Управление состоянием в редьюсере
- Отправка данных вглубь с помощью контекста
- Масштабирование состояния с редьюсером и контекстом
Продвинутые темы
Некоторым из ваших компонентов может потребоваться управление и синхронизация с системами вне React. Например, вам может потребоваться сфокусировать ввод с помощью API браузера, воспроизвести и приостановить видеопроигрыватель, реализованный без React, или подключиться и прослушать сообщения с удаленного сервера. В этой части курса по Реакт вы узнаете о лозейках, позволяющих «выйти за пределы» React и подключиться к внешним системам. Большая часть логики вашего приложения и потока данных не должны полагаться на эти функции.- Доступ к данным через рефы
- Управление DOM с помощью рефов
- Синхронизация с помощью эффектов
- Вам может не понадобиться эффект
- Жизненный цикл реактивных эффектов
- Отделение событий от эффектов
- Удаление лишних зависимостей эффектов
- Переиспользование логики с кастомными хуками