Permalänk
Medlem

React / Context

Halloj!
Tänkte höra med någon som har hygglig erfarenhet av React och som byggt/jobbat med det, angående context och state osv.
Finns det något rätt/fel vad gäller lokalt eller globalt state och ska man hålla funktioner lokalt så gott det går?
Om jag t ex har en login-funktion, är det då självklart att ha den i Login-komponenten eller brukar man skicka ned den ifrån providern?

Permalänk
Medlem

Det finns lika många religioner runt det som det finns sätt att göra det.
Dom riktlinjer jag (vi) brukar köra med är:
Att inte komplicera det i onödan, dvs gör inte hundratals små komponenter för en app som är enkel i sig. Var pragmatisk och gör det som gör det lättast att underhålla och förstå senare. Tex används inte loginfunktionen någon annan stans finns det ingen anledning att inte ha den i loginkomponenten. Det är i princip bara när du använder en komponent/funktion mer än på 2-3 ställen som det kan vara mening att bryta ut (rule of 3)
Ang state så lägger många allt i globalt state, vilket är lätt och smidigt till en gräns. Samma filosofi kan tillämpas där; har du data som konsumeras på fler ställen i olika komponenter: lägg det i globalt state, tex användaruppgifter o rättigheter kan vara sånt.

TL:DR; Börja smått o lokalt och bryt ut o globalisera efter behov.

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem

Var ett tag sedan jag använde context så kan ha fel, men tror det är smidigt med flera reducers (eller en global) som du sedan confar med olika actions för vad du vill göra (likt redux).

Permalänk
Medlem

Så här tycker jag om att göra. Lätt att följa och intuitivt enligt mig.

authReducer.ts

export type AuthType = { isSignedIn: boolean; } export enum AuthTypes { SetIsSignedIn = 'AUTH_SET_IS_SIGNED_IN', } type AuthPayload = { [AuthTypes.SetIsSignedIn]: { isSignedIn: boolean; }; } export type AuthActions = ActionMap<AuthPayload>[keyof ActionMap<AuthPayload>]; export const authReducer = (state: AuthType, action: AuthActions | ApplicationActions) => { switch (action.type) { case AuthTypes.SetIsSignedIn: return { ...state, isSignedIn: action.payload.isSignedIn }; default: return { ...state } } };

context.tsx

export type StateType = { auth: AuthType; application: ApplicationType; } const localStateItem = localStorage.getItem('state'); const initialState: StateType = { auth: { isSignedIn: false }, application: { theme: 'dark' } }; const storedState: StateType = localStateItem ? JSON.parse(localStateItem) : initialState; // ... const AppContext = createContext<{ state: StateType; dispatch: Dispatch<AuthActions | ApplicationActions>; }>({ state: storedState, dispatch: () => null }); const mainReducer = ({ auth, application }: StateType, action: AuthActions | ApplicationActions) => ({ auth: authReducer(auth, action), application: applicationReducer(application, action) }); const AppProvider: React.FC = ({ children }) => { const [state, dispatch] = useReducer(mainReducer, storedState); useEffect(() => { localStorage.setItem('state', JSON.stringify(state)); }, [state]); return ( <AppContext.Provider value={{ state, dispatch }}> {children} </AppContext.Provider> ) }; export { AppProvider, AppContext };

Login.tsx

const Login: React.FC = () => { const { state, dispatch } = useContext(AppContext); const handleSignIn = () => { dispatch({ type: AuthTypes.SetIsSignedIn, payload: { isSignedIn: true } }); }; const handleSignOut = () => { dispatch({ type: AuthTypes.SetIsSignedIn, payload: { isSignedIn: false } }); }; return ( <div className="Login"> {!state.auth.isSignedIn && <button onClick={handleSignIn}>Sign in</button>} {state.auth.isSignedIn && <button onClick={handleSignOut}>Sign out</button>} </div> ) } export default Login;

Permalänk
Medlem

Var bara försiktigt med hur du använder Context. Viktigt att du inte stoppar in variabler som är relativt ostabila högt upp i komponent-trädet, vilket kan förorsaka onödiga omrenderingar och därmed försämrar prestandan avsevärt.

Permalänk

Jag brukar använda nåt state lib (gillar zustand) som sköter allt state åt mig, så skilja på allt state-manipulerande från presentationsfunktionerna, men jag är en react-noob så...