Что нужно знать о Redux - action/dispatch/reducer/store
2 года назад·3 мин. на чтение
В этой статье рассмотрим работу с Redux - его основные понятия, и как Redux работает с данными.
Redux - это стэйт менеджер для JS приложений. Он может работать не только в React приложениях. Просто так сложилось исторически, что они часто упоминаются вместе.
Redux хранит состояние в дереве объектов внутри единого стора. Единственная возможность изменить состояние - отправить action. Action это объект, который описывает действие. Он как бы отвечает на вопрос "Что я хочу изменить в состоянии?".
Далее action попадает в reducer, где описано как состояние должно быть изменено ("Как я хочу изменить состояние?").
Action’ы добавляют порядок в происходящие изменения. Action - это объект, и его можно залогировать и последовательно отслеживать как меняется состояние.
Подытожив, можно вывести три принципа Redux:
Далее Redux вызывает переданный в него редьюсер. В редьюсер отправляется два аргумента - текущее состояние (
// types.js const ADD_TODO = "ADD_TODO"
// actions.js import { ADD_TODO } from "./types.js" export const addTodoAction = { type: ADD_TODO, payload: { id: 1, text: "Изучить Redux", done: false } }
// todo-reducer.js import { ADD_TODO } from "./types.js" export const todoReducer = (state = [], action) => { switch (action.type) { case ADD_TODO: { const item = action.payload return [...state, item] } default: return state } }
Для чего нужен Redux?
Redux и в целом любая другая система работы с состоянием нужна для контроля над состоянием. Веб приложения усложняются, добавляются новые фичи и контроль над приложением теряется. Становится сложно охватывать большой проект как единое целое. Становится cложно передавать изменения. Встроенными способами в React их приходилось бы передавать по цепочке от одного компонента в другой или через Context API. По дороге обновленное состояние может также влиять на другие компоненты и т.д. И такая бесконтрольность расползается по всему проекту и может послужить появлению новых багов и добавит сложность в отладке. Теряется прозрачность того что происходит.- Единственный источник правды - единый стор, который меняются и всегда содержит актуальные данные.
- Состояние - только для чтения. Нельзя менять его напрямую - только через action’ы.
- Изменения делаются только при помощи чистых функций.
- Эти функции (редьюсеры) принимают в качестве аргумента старое состояние и возвращают обновленное состояние. И всегда при одних и тех же данных результат этих функций будет одинаков.
Понятия в Redux
Action
Action (экшн) - это источник данных в стор, Action включает тип и некоторую информацию (payload). Тип обычно имеет строковое значение. Он нужен чтобы reducer понимал какой action был отправлен. Далее к стору будет применен payload.Reducer
Reducer (редьюсер) - это функция, которая определяет как должно меняться состояние в зависимости от аction’а. Редьюсеры должны быть чистым функциями - они должны вычислить следующее состояние и вернуть новый объект состояния. Никаких сайд эффектов, мутаций состояния, и вызовов API в редьюсере быть не должно.Store
Store - объединяет аction’ы и редьюсеры- Хранит состояние приложения.
- Предоставляет доступ к состоянию через
getState
. - Позволяет изменять состояние через
dispatch
. - Регистрирует подписчиков через
subscribe
.
dispatch
, передав в нее action.
// App.jsx import { useDispatch } from "react-redux" import { ADD_TODO } from "./types.js" export default App() { const dispatch = useDispatch() const handleTodoAdd = () => { dispatch({ type: ADD_TODO, payload: { id: 1, text: "Изучить Redux", done: false }, }) } return ( <button type="button" onClick={handleTodoAdd}>Добавить todo</button> ) }
state
) и action
.
Redux сохраняет весь объект, который вернулся из корневого редьюсера. Почему редьюсер - корневой? В Redux передается один редьюсер, но его можно разделить на несколько и собрать вместе при помощи// todo-reducer.js import { ADD_TODO } from "./types.js" export const todoReducer = (state = [], action) => { switch (action.type) { case ADD_TODO: { const item = action.payload return [...state, item] } default: return state } }
combineReducers
. Результатом этой функции будет корневой редьюсер. Обычно это делается, когда в приложении есть несколько модулей и есть смысл разделить большой редьюсер на несколько маленьких. Но для мелких приложений это совсем не обязательно.
Как уже упоминалось, Redux работает не только с ReactJS. Это универсальный инструмент. Однако для того чтобы использовать его в ReactJS нужен специальный байндинг, который ставится как отдельный пакет -// reducers.js import { combineReducers } from "redux" import { todoReducer } from "./todo-reducer" export const rootReducer = combineReducers({ todos: todoReducer, })
react-redux
.
Как подключить Redux к ReactJS проекту
Установить Redux с помощью команды.Проинициализироватьnpm i redux react-redux
store
и обернуть приложение тегом <Provider>
c переданным в него объектом store
.
// index.js import React from "react" import ReactDOM from "react-dom/client" import { createStore } from "redux" import { Provider } from "react-redux" import App from "./App" import { rootReducer } from "./reducers" const store = createStore(rootReducer) const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );
Как подключить шрифт в React
2 года назад·3 мин. на чтение
Рассмотрим три быстрых способах подключения шрифтов в React приложение.
font
В HTML используется для указания начертания, размера шрифта, типографики текста. Вы можете добавить шрифты в свое React приложение разными способами.
Способ 1. С использованием link
Мы можем ссылаться на любые шрифты из Интернета, с помощью тега <link>
внутри HTML-файла. Рассмотрим пример применения Google Fonts шрифта с помощью тега <link>
.
- Переходим в fonts.google.com
- Кликаем на шрифт

- Кликаем на “Select Regular 400” (или на любые другие выбранные виды, можно несколько)

- Нажимаем на иконку “View selected families” сверху справа.

- В появившемся боковом меню переходим в секцию “Use on the web” и копируем код, расположенный под
<link>

- Переходим в
index.html
. Если ваше приложение создано с помощьюcreate-react-app
, тоindex.html
находится в папкеpublic
. Вставляем код, скопированный в п.5 внутрь<head>
.
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
- На сайте Google Fonts в том же боковом меню находим секцию “CSS rules to specify families” и копируем код.

- Переходим в CSS файл и добавляем следующий стиль, вставляем скопированный код:
.font-roboto { font-family: 'Roboto', sans-serif; /* скопированный код */ }
- Применяем этот стиль в любом React компоненте
// App.jsx import './App.css'; function App() { return ( <div className="font-roboto"> <p>Hello</p> </div> ); } export default App;
Способ 2. С использованием Web Font Loader
Web Font Loader помогает загружать шрифты из Google Fonts, Typekit, Fonts.com и Fontdeck, а также самостоятельно размещенные веб-шрифты. Он разработан совместно компаниями Google и Typekit. Давайте посмотрим, как загрузить несколько шрифтов из Google Fonts и использовать их в компоненте React.- Установим
webfontloader
илиyarn add webfontloader
npm i webfontloader
- Импортируем
webloader
в компонент
import WebFont from 'webfontloader';
- Загружаем нужные шрифты, используя имя шрифта. Лучше использовать хук
useEffect
и позволить ему выполняться один раз при загрузке компонента. Поскольку шрифты должны быть загружены только один раз в приложении, вы можете загрузить их в файлеindex.js
.
Здесь мы загружаем шрифты 'Droid Sans' и 'Chilanka'.useEffect(() => { WebFont.load({ google: { families: ['Droid Sans', 'Chilanka'] } }); }, []);
- Теперь вы можете использовать эти шрифты в компоненте React с помощью атрибута
className
илиstyle
. Чтобы использовать атрибутclassName
, создайте CSS-класс в файле.css
.
Затем, в методе.font-loader { font-family: 'Chilanka'; }
render()
компонента добавьте следующее.
Или, с атрибутом<div className="font-loader"> Hello, World! </div>
style
<div style={{fontFamily: 'Droid Sans'}}> Hello, World! </div>
Способ 3. С использованием @font-face
Иногда шрифты должны быть загружены локально и упакованы в приложение.
@font-face
- это правило CSS для определения имени шрифта путем указания на него с помощью URL.
-
Создадим папку
fonts
в каталогеsrc
. -
Загрузим необходимые шрифты. В этом примере мы загрузим шрифт
Lobster
. Для этого выберем шрифт в Google Fonts, нажмем “Download family” и распакуем архив.

- Скопируем содержимое в папку
src\fonts
.

- Затем импортируем шрифты в файл
index.js
.
import './fonts/Lobster/Lobster-Regular.ttf';
- В файл
index.css
добавим
@font-face { font-family: "LobsterRegular"; src: local("LobsterRegular"), url("./fonts/Lobster/Lobster-Regular.ttf") format("truetype"); font-weight: normal; }
- Теперь добавим имя класса в файл
App.css
, который использует этот шрифт.
.font-lobster { font-family: "LobsterRegular"; }
- Применяем этот стиль в любом React компоненте
// App.jsx import './App.css'; function App() { return ( <div className="font-lobster"> <p>Hello</p> </div> ); } export default App;