Jest
Jest - это тестовый фреймворк для JavaScript-кода. Create React App использует Jest из коробки.
Возможности Jest
👉 подмена области рендеринга с помощью jsdom
тесты будут выполняться вне настоящего браузера, следовательно его поведение нужно имитировать.
👉 подмена функций
особенно удобно при получении данных через апи, позволяет избежать отправки реального запроса, а лишь сымитировать его, получив предсказуемые данные
👉 фиктивные модули
позволяет заменить сторонние модули, от которых зависит тестируемый компонент, если они неправильно работают в среде тестирования или вообще не нужны для тестирования
👉 фиктивные таймеры
позволяют контролировать (например, ускорять) функции, связанные со временем
#документация #тестирование
Jest - это тестовый фреймворк для JavaScript-кода. Create React App использует Jest из коробки.
Возможности Jest
👉 подмена области рендеринга с помощью jsdom
тесты будут выполняться вне настоящего браузера, следовательно его поведение нужно имитировать.
👉 подмена функций
особенно удобно при получении данных через апи, позволяет избежать отправки реального запроса, а лишь сымитировать его, получив предсказуемые данные
👉 фиктивные модули
позволяет заменить сторонние модули, от которых зависит тестируемый компонент, если они неправильно работают в среде тестирования или вообще не нужны для тестирования
👉 фиктивные таймеры
позволяют контролировать (например, ускорять) функции, связанные со временем
#документация #тестирование
jestjs.io
Тестирование в React: подготовка и завершение
Чтобы протестировать компонент, его нужно "отрендерить" в среде исполнения - создать элемент-контейнер для монтирования компонента, а после завершения теста удалить его. Для этих действий используются функции фреймворка Jest:
- beforeEach (создание контейнера)
- afterEach (очистка и удаление контейнера)
Для очистки контейнера можно использовать метод ReactDOM.unmountComponentAtNode.
#документация #тестирование
Чтобы протестировать компонент, его нужно "отрендерить" в среде исполнения - создать элемент-контейнер для монтирования компонента, а после завершения теста удалить его. Для этих действий используются функции фреймворка Jest:
- beforeEach (создание контейнера)
- afterEach (очистка и удаление контейнера)
Для очистки контейнера можно использовать метод ReactDOM.unmountComponentAtNode.
#документация #тестирование
Утилиты для тестирования
Пакет react-dom предоставляет набор утилитарных функция для тестирования компонентов - react-dom/test-utils.
Раздел в документации (рус.): https://ru.reactjs.org/docs/test-utils.html
- act - имитация рендера компонента
- isElement(element) - проверка на React-элемент
- isElementOfType(element, componentClass) - проверка на тип элемента
- isDOMComponent(instance) - проверка на DOM-элемент
- isCompositeComponent(instance) - проверка на пользовательский компонент (классовый или функциональный, не важно)
- isCompositeComponentWithType(instance, componentClass) - проверка на тип пользовательского компонента
- findAllInRenderedTree(tree, testCallback) - поиск компонентов в дереве с помощью коллбэка (должен вернуть true или false)
- scryRenderedDOMComponentsWithClass(tree, className) - поиск DOM-элементов с указанным классом в дереве
- findRenderedDOMComponentWithClass(tree, className) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- scryRenderedComponentsWithType(tree, componentClass) - поиск компонентов с указанным классом
- findRenderedComponentWithType(tree, componentClass) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- renderIntoDocument(element)
- Simulate.{eventName}(element,[eventData]) - симулировать отправку события
#документация #тестирование
Пакет react-dom предоставляет набор утилитарных функция для тестирования компонентов - react-dom/test-utils.
Раздел в документации (рус.): https://ru.reactjs.org/docs/test-utils.html
- act - имитация рендера компонента
- isElement(element) - проверка на React-элемент
- isElementOfType(element, componentClass) - проверка на тип элемента
- isDOMComponent(instance) - проверка на DOM-элемент
- isCompositeComponent(instance) - проверка на пользовательский компонент (классовый или функциональный, не важно)
- isCompositeComponentWithType(instance, componentClass) - проверка на тип пользовательского компонента
- findAllInRenderedTree(tree, testCallback) - поиск компонентов в дереве с помощью коллбэка (должен вернуть true или false)
- scryRenderedDOMComponentsWithClass(tree, className) - поиск DOM-элементов с указанным классом в дереве
- findRenderedDOMComponentWithClass(tree, className) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- scryRenderedComponentsWithType(tree, componentClass) - поиск компонентов с указанным классом
- findRenderedComponentWithType(tree, componentClass) - то же, что и предыдущий метод, но возвращает единственный результат или исключение
- renderIntoDocument(element)
- Simulate.{eventName}(element,[eventData]) - симулировать отправку события
#документация #тестирование
ru.legacy.reactjs.org
Утилиты для тестирования – React
JavaScript-библиотека для создания пользовательских интерфейсов
Тестирование простого компонента
Самый примитивный пример тестирования компонента:
https://codesandbox.io/s/testing-react-junior-i6ldm?file=/src/Hello.test.js
- beforeEach (метод Jest) - создание контейнера для рендера
- ReactDOM.unmountComponentAtNode - размонтирование React-компонента из контейнера после выполнения теста
- afterEach (метод Jest) - удаление контейнера после выполнения теста
- it (метод Jest) - объявление блока тестов
- act (вспомогательная функция из пакета react-dom/test-utils) - обеспечивает завершенность процесса рендеринга компонента перед выполнением тестов
- ReactDOM.render - рендерит компонент
- expect (метод Jest) - осуществляет проверку некоторого утверждения.
Jest предоставляет множество различных проверок (полный список здесь https://jestjs.io/docs/expect), мы воспользовались для примера самой простой - toBe, которая проверяет равенство примитивных значений или ссылок на объекты.
Результаты выполнения тестов можно увидеть во вкладке Tests.
#документация #примерыкода #тестирование
Самый примитивный пример тестирования компонента:
https://codesandbox.io/s/testing-react-junior-i6ldm?file=/src/Hello.test.js
- beforeEach (метод Jest) - создание контейнера для рендера
- ReactDOM.unmountComponentAtNode - размонтирование React-компонента из контейнера после выполнения теста
- afterEach (метод Jest) - удаление контейнера после выполнения теста
- it (метод Jest) - объявление блока тестов
- act (вспомогательная функция из пакета react-dom/test-utils) - обеспечивает завершенность процесса рендеринга компонента перед выполнением тестов
- ReactDOM.render - рендерит компонент
- expect (метод Jest) - осуществляет проверку некоторого утверждения.
Jest предоставляет множество различных проверок (полный список здесь https://jestjs.io/docs/expect), мы воспользовались для примера самой простой - toBe, которая проверяет равенство примитивных значений или ссылок на объекты.
Результаты выполнения тестов можно увидеть во вкладке Tests.
#документация #примерыкода #тестирование
Mock-функции в Jest
Mock-функция - это фиктивная реализация некоторого интерфейса, предназначенная для упрощения тестирования.
Создать такую функцию можно с помощью метода jest.fn(). В качестве необязательного аргумента можно передать реализацию мок-функции (которая будет вызываться при обращении к мок-функции). Реализацию можно также установить после создания, с помощью метода mockFn.mockImplementation(fn).
Подробнее о моках в документации Jest: https://jestjs.io/docs/mock-function-api
У мок-функций есть ряд полезных методов, позволяющих, например, посмотреть все вызовы.
Кроме того, передав мок-функцию в метод expect, мы получаем еще ряд полезных утверждений вроде toHaveBeenCalled().
Помимо простых моков есть еще шпионы (spies). Они имеют интерфейс мок-функции и отслеживают вызовы некоторого существующего метода. Создать шпиона можно с помощью метода jest.spyOn(object, methodName) - он будет отслеживать вызовы object[methodName]. Для них также можно переопределить существующую функциональность с помощью mockFn.mockImplementation().
Например, можно установить шпиона для метода fetch:
Mock-функция - это фиктивная реализация некоторого интерфейса, предназначенная для упрощения тестирования.
Создать такую функцию можно с помощью метода jest.fn(). В качестве необязательного аргумента можно передать реализацию мок-функции (которая будет вызываться при обращении к мок-функции). Реализацию можно также установить после создания, с помощью метода mockFn.mockImplementation(fn).
Подробнее о моках в документации Jest: https://jestjs.io/docs/mock-function-api
У мок-функций есть ряд полезных методов, позволяющих, например, посмотреть все вызовы.
Кроме того, передав мок-функцию в метод expect, мы получаем еще ряд полезных утверждений вроде toHaveBeenCalled().
Помимо простых моков есть еще шпионы (spies). Они имеют интерфейс мок-функции и отслеживают вызовы некоторого существующего метода. Создать шпиона можно с помощью метода jest.spyOn(object, methodName) - он будет отслеживать вызовы object[methodName]. Для них также можно переопределить существующую функциональность с помощью mockFn.mockImplementation().
Например, можно установить шпиона для метода fetch:
jest.spyOn(global, "fetch").mockImplementation(setupFetchStub)#тестирование #jest
jestjs.io
The Jest Object · Jest
The jest object is automatically in scope within every test file. The methods in the jest object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via import from '@jest/globals'.
Замена методов
Некоторые функции (вроде запросов данных) могут вызывать проблемы при тестировании: они долго выполняются, могут прерываться неожиданными ошибками, которые не имеют отношения к тестам, а также возвращают неопределенные данные.
Такие функции можно заменить шпионами Jest (jest.spyOn) и установить для них фиктивную реализацию.
https://codesandbox.io/s/mock-methods-react-junior-0oxgq?file=/src/Pokemon.test.js
Примечание: в примере запрос данных осуществляется с помощью метода Utils.fetch и шпион устанавливается именно для него:
Это сделано для демонстрации, так как в codesandbox не получилось установить шпиона для global.fetch. В нормальной среде выполнения должно быть:
#документация #тестирование #примерыкода
Некоторые функции (вроде запросов данных) могут вызывать проблемы при тестировании: они долго выполняются, могут прерываться неожиданными ошибками, которые не имеют отношения к тестам, а также возвращают неопределенные данные.
Такие функции можно заменить шпионами Jest (jest.spyOn) и установить для них фиктивную реализацию.
https://codesandbox.io/s/mock-methods-react-junior-0oxgq?file=/src/Pokemon.test.js
Примечание: в примере запрос данных осуществляется с помощью метода Utils.fetch и шпион устанавливается именно для него:
jest.spyOn(Utils, 'fetch')
Это сделано для демонстрации, так как в codesandbox не получилось установить шпиона для global.fetch. В нормальной среде выполнения должно быть:
jest.spyOn(global, 'fetch')
#документация #тестирование #примерыкода
CodeSandbox
Mock methods. React Junior - CodeSandbox
Mock methods. React Junior by furrycat.web using react, react-dom, react-scripts
Фиктивные модули
Создать фиктивную реализацию можно не только для функции, но и для целого модуля.
Для этого предназначен метод jest.mock(moduleName, factory, options).
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#mocking-modules
#документация #тестирование #jest
Создать фиктивную реализацию можно не только для функции, но и для целого модуля.
Для этого предназначен метод jest.mock(moduleName, factory, options).
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#mocking-modules
#документация #тестирование #jest
jestjs.io
The Jest Object · Jest
The jest object is automatically in scope within every test file. The methods in the jest object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via import from '@jest/globals'.
События при тестировании
Создать событие на элементе можно стандартным методом dispatchEvent, передав ему объект события.
Важно: Объекту события нужно передать опцию
#документация #тестирование
Создать событие на элементе можно стандартным методом dispatchEvent, передав ему объект события.
Важно: Объекту события нужно передать опцию
bubbles: true
, чтобы обработчик событий React его увидел и автоматически передал в корень документа.#документация #тестирование
Фиктивные таймеры
Jest предоставляет моки и для таймеров (setTimeout, setInterval): https://jestjs.io/ru/docs/timer-mocks.
👉 jest.useFakeTimers() и jest.useRealTimers() позволяют переключить режим работы таймеров.
👉 jest.advanceTimersByTime(ms) сдвигает время на указанное количество милисекунд.
Есть еще пара методов, которые могут пригодиться: runAllTimers и runOnlyPendingTimers.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#timers
#документация #тестирование #jest
Jest предоставляет моки и для таймеров (setTimeout, setInterval): https://jestjs.io/ru/docs/timer-mocks.
👉 jest.useFakeTimers() и jest.useRealTimers() позволяют переключить режим работы таймеров.
👉 jest.advanceTimersByTime(ms) сдвигает время на указанное количество милисекунд.
Есть еще пара методов, которые могут пригодиться: runAllTimers и runOnlyPendingTimers.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#timers
#документация #тестирование #jest
Снапшоты
Jest позволяет делать снапшоты - сохранять "снимки" данных. Иначе говоря, сохраняется результат рендера компонента. При внесении изменений этот "снимок" изменится.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#snapshot-testing
#документация #тестирование #jest
Jest позволяет делать снапшоты - сохранять "снимки" данных. Иначе говоря, сохраняется результат рендера компонента. При внесении изменений этот "снимок" изменится.
Пример в документации (рус.): https://ru.reactjs.org/docs/testing-recipes.html#snapshot-testing
#документация #тестирование #jest
ru.legacy.reactjs.org
Рецепты тестирования – React
JavaScript-библиотека для создания пользовательских интерфейсов
Тестовый рендерер
React предоставляет пакет react-test-renderer, который может быть полезен для тестирования. Это тестовый рендерер, который умеет рендерить React-компоненты в обычные JavaScript-объекты без использования DOM или мобильного окружения - своего рода аналог снапшотов.
Подробный обзор тестового рендера в документации (рус.): https://ru.reactjs.org/docs/test-renderer.html
Руководство по тестированию с помощью снимков в документации Jest: https://jestjs.io/ru/docs/snapshot-testing
#документация #тестирование
React предоставляет пакет react-test-renderer, который может быть полезен для тестирования. Это тестовый рендерер, который умеет рендерить React-компоненты в обычные JavaScript-объекты без использования DOM или мобильного окружения - своего рода аналог снапшотов.
Подробный обзор тестового рендера в документации (рус.): https://ru.reactjs.org/docs/test-renderer.html
Руководство по тестированию с помощью снимков в документации Jest: https://jestjs.io/ru/docs/snapshot-testing
#документация #тестирование
ru.legacy.reactjs.org
Тестовый рендерер – React
JavaScript-библиотека для создания пользовательских интерфейсов
Первый подход к документации React завершен - и завершен неплохо! Разобрались с основными понятиями, заглянули одним глазом под капот, потрогали тестирование.
Осталось еще несколько незатронутых разделов, и самый важный из них - Участие в проекте. Он сложный, не для новичков, вернемся к нему попозже.
На что нужно обратить более пристальное внимание?
На самом деле, на многое:
👉 тестирование,
👉 интеграция стилей в проект,
👉 типизация,
👉 тесное взаимодействие с DOM (например, сложные анимации),
👉 оптимизация.
Обязательно всем этим займемся. А сейчас переходим к практическому разделу документации - туториалу по созданию игры на React.
Осталось еще несколько незатронутых разделов, и самый важный из них - Участие в проекте. Он сложный, не для новичков, вернемся к нему попозже.
На что нужно обратить более пристальное внимание?
На самом деле, на многое:
👉 тестирование,
👉 интеграция стилей в проект,
👉 типизация,
👉 тесное взаимодействие с DOM (например, сложные анимации),
👉 оптимизация.
Обязательно всем этим займемся. А сейчас переходим к практическому разделу документации - туториалу по созданию игры на React.
ru.reactjs.org
Устройство кодовой базы – React
JavaScript-библиотека для создания пользовательских интерфейсов
Крестики-нолики
https://ru.reactjs.org/tutorial/tutorial.html
Документация предлагает нам написать игру в крестики-нолики: игровое поле 3х3, два игрока, которые ходят по очереди. Победитель определяется по заполненности горизонтального, вертикального или диагонального ряда.
Бонусом идет еще сохранение истории ходов и возможность перейти на любой предыдущий ход и продолжить игру с него.
Игра создается по этапам, для каждого есть заготовка в codepen - можно перейти и разобраться.
Пример выполнен на классовых компонентах, потому что он довольно старый, хуков тогда еще не было, а состояние нужно было где-то хранить.
Этап 1. Состояние игры и рендер игрового поля
https://codepen.io/gaearon/pen/QvvJOv?editors=0010
Создаются компоненты Game, Board и Square - отдельная клетка поля.
Состояние игры squares - это массив значений всех клеток (может быть null, 'x' или 'o').
По философии React состояние должно подниматься до ближайшего заинтересованного компонента, поэтому оно будет располагаться в компоненте Board и передаваться в каждую клетку Square через пропсы. Также в каждую клетку будет передаваться обработчик клика, необходимый для изменения состояния клетки при клике (устновка "крестика" или "нолика").
Здесь мы видим четкий пример однонаправленного потока данных и модели событий. Square является управляемым компонентом, поскольку полностью контролируется из Board.
Важно также обратить внимание, что при изменении состояния одной клетки полностью обновляется весь массив squares - это пример иммутабельности данных.
Этап 2. Очередность хода
https://codepen.io/gaearon/pen/KmmrBy?editors=0010
Чтобы крестики и нолики чередовались, добавляется еще одно поле в состояние xIsNext, которое инвертируется после каждого хода.
Этап 3. Определение победителя
https://codepen.io/gaearon/pen/LyyXgK?editors=0010
Наконец, добавляется проверка заполненности рядов, которая осуществляется после каждого хода.
Этап 4. История ходов
https://codepen.io/gaearon/pen/gWWZgR?editors=0010
История ходов - это просто массив последовательных слепков состояний для каждого хода. При возвращении на определенный шаг мы можем просто взять его слепок и заменить им текущее состояние.
Тут есть важный момент: историй шагов будет пользоваться не только в компоненте Board, но и в списке ходов. Поэтому состояние поднимается из Board до Game.
#документация #примерыкода
https://ru.reactjs.org/tutorial/tutorial.html
Документация предлагает нам написать игру в крестики-нолики: игровое поле 3х3, два игрока, которые ходят по очереди. Победитель определяется по заполненности горизонтального, вертикального или диагонального ряда.
Бонусом идет еще сохранение истории ходов и возможность перейти на любой предыдущий ход и продолжить игру с него.
Игра создается по этапам, для каждого есть заготовка в codepen - можно перейти и разобраться.
Пример выполнен на классовых компонентах, потому что он довольно старый, хуков тогда еще не было, а состояние нужно было где-то хранить.
Этап 1. Состояние игры и рендер игрового поля
https://codepen.io/gaearon/pen/QvvJOv?editors=0010
Создаются компоненты Game, Board и Square - отдельная клетка поля.
Состояние игры squares - это массив значений всех клеток (может быть null, 'x' или 'o').
По философии React состояние должно подниматься до ближайшего заинтересованного компонента, поэтому оно будет располагаться в компоненте Board и передаваться в каждую клетку Square через пропсы. Также в каждую клетку будет передаваться обработчик клика, необходимый для изменения состояния клетки при клике (устновка "крестика" или "нолика").
Здесь мы видим четкий пример однонаправленного потока данных и модели событий. Square является управляемым компонентом, поскольку полностью контролируется из Board.
Важно также обратить внимание, что при изменении состояния одной клетки полностью обновляется весь массив squares - это пример иммутабельности данных.
Этап 2. Очередность хода
https://codepen.io/gaearon/pen/KmmrBy?editors=0010
Чтобы крестики и нолики чередовались, добавляется еще одно поле в состояние xIsNext, которое инвертируется после каждого хода.
Этап 3. Определение победителя
https://codepen.io/gaearon/pen/LyyXgK?editors=0010
Наконец, добавляется проверка заполненности рядов, которая осуществляется после каждого хода.
Этап 4. История ходов
https://codepen.io/gaearon/pen/gWWZgR?editors=0010
История ходов - это просто массив последовательных слепков состояний для каждого хода. При возвращении на определенный шаг мы можем просто взять его слепок и заменить им текущее состояние.
Тут есть важный момент: историй шагов будет пользоваться не только в компоненте Board, но и в списке ходов. Поэтому состояние поднимается из Board до Game.
#документация #примерыкода
ru.legacy.reactjs.org
Введение: знакомство с React – React
JavaScript-библиотека для создания пользовательских интерфейсов
Крестики-нолики
https://codesandbox.io/s/tic-tac-toe-react-junior-8wb1t
Моя версия демо-игры Крестики-Нолики из документации.
Классовые компоненты заменены на функциональные + хуки. Для хранения сложного состояния используется useReducer и система событий.
Также внесены добавления, рекомендованные в документации:
👉 Отобразите позицию для каждого хода в формате (колонка, строка) в списке истории ходов. (для каждого слепка состояния в history кроме squares сохраняется coords - позиция сделанного хода).
👉 Выделите выбранный элемент в списке ходов. (Простое сравнение индексов)
👉 Перепишите Board, используя вложенные циклы для создания клеток, вместо их жёсткого кодирования.
👉 Добавьте переключатель, который позволит вам сортировать ходы по возрастанию или по убыванию. (Главное не потерять порядок ходово)
👉 Когда кто-то выигрывает, подсветите три клетки, которые привели к победе. (При расчете победителя кроме символа "Х" или "О" передается также выигрышная комбинация)
👉 Когда победителя нет, покажите сообщение о том, что игра окончилась вничью. (Проверка на наличие свободных клеток)
#документация #примерыкода
https://codesandbox.io/s/tic-tac-toe-react-junior-8wb1t
Моя версия демо-игры Крестики-Нолики из документации.
Классовые компоненты заменены на функциональные + хуки. Для хранения сложного состояния используется useReducer и система событий.
Также внесены добавления, рекомендованные в документации:
👉 Отобразите позицию для каждого хода в формате (колонка, строка) в списке истории ходов. (для каждого слепка состояния в history кроме squares сохраняется coords - позиция сделанного хода).
👉 Выделите выбранный элемент в списке ходов. (Простое сравнение индексов)
👉 Перепишите Board, используя вложенные циклы для создания клеток, вместо их жёсткого кодирования.
👉 Добавьте переключатель, который позволит вам сортировать ходы по возрастанию или по убыванию. (Главное не потерять порядок ходово)
👉 Когда кто-то выигрывает, подсветите три клетки, которые привели к победе. (При расчете победителя кроме символа "Х" или "О" передается также выигрышная комбинация)
👉 Когда победителя нет, покажите сообщение о том, что игра окончилась вничью. (Проверка на наличие свободных клеток)
#документация #примерыкода
CodeSandbox
Tic Tac Toe. React Junior - CodeSandbox
Tic Tac Toe. React Junior by furrycat.web using react, react-dom, react-scripts
10 способов стилизации React-приложений
React не работает со стилями и не имеет предпочтений в том, как стилизовать приложение. Это значит, что мы можем действовать по своему усмотрению: можем писать инлайновый стили или по традиции подключать внешние файлы. Плюс есть еще десяток способов, которые пытаются добавить в CSS возможности JS и расширить его.
Нет никаких сомнений, что в разных ситуациях лучшим решением будут разные техники. Но чтобы понимать, что выбрать, нужно знать, что вообще существует.
В статье (рус.): https://www.cat-in-web.ru/10-ways-to-style-react/ представлен краткий обзор способов стилизации React-компонентов с примерами кода.
👉 инлайновые стили
👉 внешние таблицы стилей
👉 CSS-модули - решают проблему конфликтов стилей для классов с одинаковыми именами. В разных компонентах может быть класс .container, оформленный по-разному
👉 CSS-препроцессоры
👉 Styled Components - стили пишутся как CSS, но могут использовать данные из JavaScript
👉 React JSS - стили в виде JS-объекта
👉 Radium - предоставляет обертку для компонентов и возможность удобно задавать стили, включая псевдоселекторы
👉 React Shadow - инкапсулирует стили компонента внутри теневого DOM
👉 JSX Style - набор компонентов для стилизации React приложений
👉 Утилитарные фреймворки
#инструменты #ссылки #стили
React не работает со стилями и не имеет предпочтений в том, как стилизовать приложение. Это значит, что мы можем действовать по своему усмотрению: можем писать инлайновый стили или по традиции подключать внешние файлы. Плюс есть еще десяток способов, которые пытаются добавить в CSS возможности JS и расширить его.
Нет никаких сомнений, что в разных ситуациях лучшим решением будут разные техники. Но чтобы понимать, что выбрать, нужно знать, что вообще существует.
В статье (рус.): https://www.cat-in-web.ru/10-ways-to-style-react/ представлен краткий обзор способов стилизации React-компонентов с примерами кода.
👉 инлайновые стили
👉 внешние таблицы стилей
👉 CSS-модули - решают проблему конфликтов стилей для классов с одинаковыми именами. В разных компонентах может быть класс .container, оформленный по-разному
👉 CSS-препроцессоры
👉 Styled Components - стили пишутся как CSS, но могут использовать данные из JavaScript
👉 React JSS - стили в виде JS-объекта
👉 Radium - предоставляет обертку для компонентов и возможность удобно задавать стили, включая псевдоселекторы
👉 React Shadow - инкапсулирует стили компонента внутри теневого DOM
👉 JSX Style - набор компонентов для стилизации React приложений
👉 Утилитарные фреймворки
#инструменты #ссылки #стили
👏1
Итак, документация закончилась, куда двигаться дальше? Страшновато делать шаг за пределы уже знакомого систематизированного маленького мирка, да? Вокруг слишком много неизвестного, но кое за что все же можно ухватиться.
Сама собой напрашивается для изучения тема интеграции стилей в React-проекты, тем более первый шаг уже сделан - самый важный, систематический, как я люблю.
Обычный скучный CSS я, конечно, разбирать не буду, с ним все ясно. Лучше попробую на вкус что-нибудь новенькое.
В планах:
- CSS модули
- Styled Components
- React JSS
- Radium
- React Shadow
- JSX Style
И на закуску - утилитарные CSS-фреймворки, с которыми уже давно хочется познакомиться.
#стили
Сама собой напрашивается для изучения тема интеграции стилей в React-проекты, тем более первый шаг уже сделан - самый важный, систематический, как я люблю.
Обычный скучный CSS я, конечно, разбирать не буду, с ним все ясно. Лучше попробую на вкус что-нибудь новенькое.
В планах:
- CSS модули
- Styled Components
- React JSS
- Radium
- React Shadow
- JSX Style
И на закуску - утилитарные CSS-фреймворки, с которыми уже давно хочется познакомиться.
#стили
Telegram
React Junior
10 способов стилизации React-приложений
React не работает со стилями и не имеет предпочтений в том, как стилизовать приложение. Это значит, что мы можем действовать по своему усмотрению: можем писать инлайновый стили или по традиции подключать внешние файлы.…
React не работает со стилями и не имеет предпочтений в том, как стилизовать приложение. Это значит, что мы можем действовать по своему усмотрению: можем писать инлайновый стили или по традиции подключать внешние файлы.…
👏1
CSS Модули
CSS модуль — это CSS файл, в котором все имена классов и анимаций имеют локальную область видимости по умолчанию.
То есть мы можем создать файл user-card.css и файл product-card.css. В каждом из этих файлов определить одинаковые классы .header, .footer, .content, .img. И при использовании в HTML стили этих классов не будут ломать друг друга, потому что они будут работать в разных контекстах - внутри карточки юзера или внутри карточки продукта. Как бы БЭМ, но без ужасно длинных имен и разного рода префиксов.
Но чтобы эта магия работала, CSS нужно обрабатывать с помощью JS, то есть включить его в сборку проекта. Вряд ли это кажется чем-то ужасным, ведь мы и так обрабатываем CSS, например, для добавления вендорных префиксов. Просто нужно обработать чуть сильнее :)
Настроив сборку определенным образом, мы сможем импортировать стили из CSS-файла как объект. При этом каждому классу, который мы определили (.header, .footer и т.д.) в этом объекте будет соответствовать уникальная строка (как БЭМ, но сгенерированная программой и совершенно точно уникальная). Именно эту строку мы и будем использовать в качестве класса.
На гитхабе нашелся профиль css-modules, будем посмотреть.
#стили
CSS модуль — это CSS файл, в котором все имена классов и анимаций имеют локальную область видимости по умолчанию.
То есть мы можем создать файл user-card.css и файл product-card.css. В каждом из этих файлов определить одинаковые классы .header, .footer, .content, .img. И при использовании в HTML стили этих классов не будут ломать друг друга, потому что они будут работать в разных контекстах - внутри карточки юзера или внутри карточки продукта. Как бы БЭМ, но без ужасно длинных имен и разного рода префиксов.
Но чтобы эта магия работала, CSS нужно обрабатывать с помощью JS, то есть включить его в сборку проекта. Вряд ли это кажется чем-то ужасным, ведь мы и так обрабатываем CSS, например, для добавления вендорных префиксов. Просто нужно обработать чуть сильнее :)
Настроив сборку определенным образом, мы сможем импортировать стили из CSS-файла как объект. При этом каждому классу, который мы определили (.header, .footer и т.д.) в этом объекте будет соответствовать уникальная строка (как БЭМ, но сгенерированная программой и совершенно точно уникальная). Именно эту строку мы и будем использовать в качестве класса.
На гитхабе нашелся профиль css-modules, будем посмотреть.
#стили
GitHub
css-modules
css-modules has 26 repositories available. Follow their code on GitHub.
Работа с CSS Modules в React-приложении
Пробуем использовать CSS-модули.
Для начала создаем новый проект React (с помощью утилиты create-react-app). Ничего особенного, всего один компонент PokemonCard. У этого компонента есть собственный файл стилей, подключенный обычным импортом (
Если попробовать импортировать из этого файла стили в виде объекта, как обещались мне статьи по CSS-модулям, то ничего не получится (в консоль выводится пустой объект, созданных CSS-классов там нет).
Посмотреть:
https://codesandbox.io/s/css-modules-start-react-junior-264oh?file=/src/components/PokemonCard/index.js:0-56
Нужно ли что-то настраивать? Нет, не нужно.
create-react-app из коробки поддерживает использование CSS модулей. Для этого просто нужно добавлять к css-файлам суффикс module. То есть вместо style.css должно быть style.module.css.
Посмотреть:
https://codesandbox.io/s/css-modules-1-react-junior-uhdec?file=/src/components/PokemonCard/index.js:0-63
Теперь в консоль выводится объект формата:
Если все же хочется копнуть поглубже или использовать модули вне create-react-app, то вся магия заключена в css-loader для webpack. У него есть опция modules, которую просто нужно включить.
#стили #примерыкода
Пробуем использовать CSS-модули.
Для начала создаем новый проект React (с помощью утилиты create-react-app). Ничего особенного, всего один компонент PokemonCard. У этого компонента есть собственный файл стилей, подключенный обычным импортом (
import style.css
).Если попробовать импортировать из этого файла стили в виде объекта, как обещались мне статьи по CSS-модулям, то ничего не получится (в консоль выводится пустой объект, созданных CSS-классов там нет).
Посмотреть:
https://codesandbox.io/s/css-modules-start-react-junior-264oh?file=/src/components/PokemonCard/index.js:0-56
Нужно ли что-то настраивать? Нет, не нужно.
create-react-app из коробки поддерживает использование CSS модулей. Для этого просто нужно добавлять к css-файлам суффикс module. То есть вместо style.css должно быть style.module.css.
Посмотреть:
https://codesandbox.io/s/css-modules-1-react-junior-uhdec?file=/src/components/PokemonCard/index.js:0-63
Теперь в консоль выводится объект формата:
{То есть каждому имени класса, которое было объявлено в файле стилей, сопоставлена уникальная строка. Эту строку нужно подставить вместо обычного класса.
card: "_src_components_PokemonCard_style_module__card",
cardImg: "_src_components_PokemonCard_style_module__cardImg",
cardHeader: "_src_components_PokemonCard_style_module__cardHeader",
cardData: "_src_components_PokemonCard_style_module__cardData",
cardFooter: "_src_components_PokemonCard_style_module__cardFooter,
}
className="cardImg"превращается в
className={styles.cardImg}Оказалось, что все очень просто и даже не нужно ничего настраивать.
Если все же хочется копнуть поглубже или использовать модули вне create-react-app, то вся магия заключена в css-loader для webpack. У него есть опция modules, которую просто нужно включить.
#стили #примерыкода
Изолированность CSS-модулей
Демонстрация изолированности модулей друг от друга:
https://codesandbox.io/s/css-modules-2-react-junior-z002o?file=/src/App.js
В приложении есть два компонента - ProductCard и UserCard. В их файлах стилей объявлены абсолютно одинаковые классы - .card, .title, .description, .img.
Но так как мы заменяем эти классы на уникальные строки, никаких конфликтов стилей не происходит.
#стили #примерыкода
Демонстрация изолированности модулей друг от друга:
https://codesandbox.io/s/css-modules-2-react-junior-z002o?file=/src/App.js
В приложении есть два компонента - ProductCard и UserCard. В их файлах стилей объявлены абсолютно одинаковые классы - .card, .title, .description, .img.
Но так как мы заменяем эти классы на уникальные строки, никаких конфликтов стилей не происходит.
#стили #примерыкода