State: reducer, Context och normalisering
Varför behövs detta?
- När props‑drilling blir tungt och flera komponenter behöver samma data.
- När state‑uppdateringar blir komplexa och kräver förutsägbarhet.
Reducer + Context
Reducer ger ett deterministiskt sätt att uppdatera state utifrån action → nytt state. Context delar detta state i trädet.
När? När flera delar av appen måste läsa/uppdatera samma state och “lyfta state” inte räcker.
import { createContext, useContext, useReducer } from 'react';
const AppContext = createContext();
function reducer(state, action) {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload };
default:
return state;
}
}
export function AppProvider({ children }) {
const [state, dispatch] = useReducer(reducer, { user: null });
const value = { state, dispatch };
return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}
export function useApp() {
const ctx = useContext(AppContext);
if (!ctx) throw new Error('useApp must be used within AppProvider');
return ctx;
}
Varför? Reducer minskar implicit logik utspridd i många setState‑anrop och gör flöden testbara.
Normalisering av data
När? När du har inbäddade listor/objekt som blir svåra att uppdatera utan buggar.
Princip: spara data “platt” per typ (entities
) och referera med ids.
Fördel: enklare uppdateringar och memoization; mindre risk för oavsiktliga re‑renders.
När extern state‑hanterare?
- Du behöver features som devtools, middleware, time‑travel, asynk‑flöden.
- Alternativ: Zustand, Redux Toolkit, Jotai. Välj när behoven finns — inte i förväg.