webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
State management · Lecția 2 din 4

Redux Toolkit

Store, acțiuni, reduceri, createSlice cu Immer și Redux în Next.

Actualizat

Ce este Redux

Redux e un model de state global cu reguli stricte:

  1. Tot state-ul global stă într-un singur store.
  2. State-ul nu se modifică direct — trimiți (dispatch) o acțiune: un obiect care descrie ce s-a întâmplat ({ type: 'cart/add', payload: item }).
  3. Un reducer — funcție pură (state, action) => newState — calculează noul state.
UIdispatch(action)acțiune→reducer(state, action) => newStatestate nou→storeselector→UIse re-randează

Avantajul: orice schimbare trece prin același loc → previzibil, testabil, cu DevTools care îți arată fiecare acțiune și pot „derula înapoi” istoria.

Redux Toolkit (RTK) e felul oficial și actual de a scrie Redux. Redux „clasic” (cu switch, constante de tip, connect) e considerat depășit.

Piesele Redux Toolkit

Piesă Ce face
configureStore creează store-ul, cu DevTools și middleware incluse
createSlice definește o bucată de state + reducerii ei; generează acțiunile automat
useSelector citește o bucată din store (componenta se re-randează doar când ea se schimbă)
useDispatch trimite acțiuni
createAsyncThunk logică asincronă (rar azi — pentru date folosești RTK Query)
RTK Query fetch + cache pentru server state — lecția următoare

Un slice

// entities/cart/model/cart-slice.ts
import { createSlice, type PayloadAction } from '@reduxjs/toolkit'

type CartItem = { id: number; qty: number }

const cartSlice = createSlice({
  name: 'cart',
  initialState: [] as CartItem[],
  reducers: {
    added(state, action: PayloadAction<number>) {
      const item = state.find(i => i.id === action.payload)
      if (item) item.qty++                         // „mutație” permisă — vezi Immer
      else state.push({ id: action.payload, qty: 1 })
    },
    removed(state, action: PayloadAction<number>) {
      return state.filter(i => i.id !== action.payload)
    },
  },
})

export const { added, removed } = cartSlice.actions
export const cartReducer = cartSlice.reducer

Immer: în createSlice poți scrie cod care pare să modifice state-ul (state.push, item.qty++). RTK folosește librăria Immer, care transformă aceste „mutații” într-un obiect nou, imutabil. Regulile din Referințe și imutabilitate rămân valabile — doar sintaxa e mai scurtă.

Store și hook-uri tipate

// shared/store/store.ts
export const makeStore = () => configureStore({ reducer: { cart: cartReducer } })

export type AppStore = ReturnType<typeof makeStore>
export type RootState = ReturnType<AppStore['getState']>
export type AppDispatch = AppStore['dispatch']

export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
'use client'
const count = useAppSelector(state => state.cart.length)
const dispatch = useAppDispatch()
<button onClick={() => dispatch(added(product.id))}>Adaugă</button>

Redux cu Next.js App Router

  • Store-ul se creează per request, nu ca variabilă globală de modul — altfel, pe server, datele unui user ajung la altul. De aceea makeStore() e o funcție.
  • Îl pui într-un Client Component StoreProvider ('use client'), creat o dată cu useRef / useState.
  • Server Components nu pot citi store-ul — ele își iau datele direct.

Când Redux Toolkit

Da Nu
aplicație mare, multe echipe, reguli stricte utile aplicație mică / medie
logică complexă cu multe tranziții, nevoie de DevTools / time-travel doar puțin UI state global
proiect existent pe Redux state care e de fapt server state

Pe scurt

  • Redux = un store, acțiuni, reduceri puri; RTK e modul actual de a-l scrie.
  • createSlice + Immer = cod scurt, rezultat imutabil.
  • În Next: store per request, în Client Component; pentru date de server → RTK Query.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.