Redux Toolkit Flashcards
Redux Toolkit
Redux Toolkit - библиотека для работы с Redux, которая упрощает создание и управление состоянием в приложениях.
Основные преимущества Redux Toolkit:
- Предоставляет функцию configureStore, которая автоматически настраивает store с лучшими практиками: включение DevTools и middleware по умолчанию;
- Использует библиотеку Immer под капотом, что позволяет писать иммутабельный код более естественно;
- Предоставляет функцию createSlice, позволяющую объединить actions и reducers в одном месте и генерирующую action creators и action types автоматически;
- Предоставляет функцию createAsyncThunk, упрощающую создание асинхронных операций, таких как запросы к API;
DevTools и Middleware по умолчанию: configureStore автоматически включает Redux DevTools и полезные middleware, такие как redux-thunk;
- Redux Toolkit включает в себя утилиты, сокращающие количество шаблонного кода, необходимого для создания actions и reducers, что делает код более читабельным и поддерживаемым.
Создавая store, нужно передать в него объект, с двумя свойствами: tasks и todolists, и указать, какие редьюсеры отвечают за обработку каждой части.
Для того,чтобы подключить Redux необходимо выполнить некоторые правила:
1. Подключение библиотеки
pnpm add @reduxjs/toolkit react-redux
2. Создать store.ts в папке app. В папке app хранится все глобальное, то что нам необходимо для проекта.
Как создается store.ts можем узнать из методических материалов.
https://redux-toolkit.js.org/tutorials/quick-start#create-a-redux-store.
import {combineReducers, configureStore} from ‘@reduxjs/toolkit’
import {tasksReducer} from ‘../model/tasks-reducer’
import {todolistsReducer} from ‘../model/todolists-reducer’
// объединение reducer’ов с помощью combineReducers
const rootReducer = combineReducers({
tasks: tasksReducer,
todolists: todolistsReducer,
})
// создание store
export const store = configureStore({
reducer: rootReducer,
})
// автоматическое определение типа всего объекта состояния
export type RootState = ReturnType<typeof>
// автоматическое определение типа метода dispatch
export type AppDispatch = typeof store.dispatch</typeof>
// для возможности обращения к store в консоли браузера
// @ts-ignore
window.store = store
3. Подключение store - необходимо обернуть в провайдер
import { createRoot } from ‘react-dom/client’
import ‘./index.css’
import { App } from ‘./app/App.tsx’
import {Provider} from “react-redux”;
import {store} from “./app/store.ts”;
createRoot(document.getElementById(‘root’)!).render(
<Provider store={store}> <App></App></Provider>
)
- В app подключаем useSelector
const todolists = useSelector<RootState, Todolist[]>(state => state.todolists)
const tasks = useSelector<RootState, TasksState>(state => state.tasks)
useSelector - берет и достает кусочек стейта в компоненту, чтобы мы могли отрисовать и посмотреть глазами в браузере. Подписывается на изменение этих данных - если поменяется стейт, то компонента перерисуется с первоначальными изменениями.
- Подключаем dispatch
const dispatch = useDispatch() - Можно также отдельно протипизировать useSelector
и useDispatch() - https://redux-toolkit.js.org/tutorials/typescript#define-typed-hooks
common -> hooks
Создаем в итоге 2 файла:
useAppSelector.ts и useAppDispatch.ts
import {RootState} from “../../app/store.ts”;
import {useSelector, useAppDispatch} from “react-redux”;
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()</AppDispatch></RootState>
В самом App можно не типизировать подробно, в результате только взять из созданных нами файлов.
const todolists = useAppSelector(state => state.todolists)
const dispatch = useAppDispatch()
- Создается одна функция селектор, впоследствии, которую можем использовать в дальнейшем.
export const selectTodolists = (state: RootState): Todolist[] => state.todolists
const todolists = useAppSelector(selectTodolists)
(state => state.todolists) - анонимная функция, пересоздается каждый раз при рендере компоненты.
- В reducer toolkit:
export const changeTodolistTitleAC = createAction<{id: string, title: string}>(‘todolists/changeTodolistTitle’)
export const changeTodolistFilterAC = createAction<{id: string, filter: FilterValues}>(‘todolists/changeTodolistFilter’)
const initialState: Todolist[] = []
export const todolistsReducer = createReducer (initialState, builder => {
builder
.addCase (deleteTodolistAC, (state, action) => {
const index = state.findIndex (todolist => todolist.id === action.payload.id)
if (index !== -1) {
state.splice (index, 1)
}
})
.addCase (createTodolistAC, (state, action) => {
state.push({…action.payload, filter: ‘all’})
})
.addCase(changeTodolistTitleAC, (state, action) => {
const todolist = state.find (todolist => todolist.id === action.payload.id)
if (todolist) {
todolist.title = action.payload.title
}
})
.addCase(changeTodolistFilterAC, (state, action) => {
const index = state.findIndex (todolist => todolist.id === action.payload.id)
if (index !== -1) {
state[index].filter = action.payload.filter
}
})
})