guides

React Context

Del state og funktioner på tværs af komponenter.

1) Hvad problem løser Context?

Normalt sender man data fra parent til child med props. Men hvis mange komponenter skal bruge samme data, kan det hurtigt blive rodet.

Prop drilling

tsx · 5 lines

tsx
1<App user={user}>
2 <Layout user={user}>
3 <Navbar user={user} />
4 </Layout>
5</App>

Context gør det muligt at lægge data ét centralt sted og hente det derfra i de komponenter, der har brug for det.

2) Opret context

UserContext.tsx

tsx · 17 lines

tsx
1"use client";
2
3
4import React, { createContext, useContext, useState } from "react";
5
6type User = {
7 name: string;
8 email: string;
9};
10
11type UserContextType = {
12 user: User | null;
13 login: (user: User) => void;
14 logout: () => void;
15};
16
17const UserContext = createContext<UserContextType | null>(null);

3) Opret provider

UserContext.tsx

tsx · 21 lines

tsx
1type Props = {
2 children: React.ReactNode;
3};
4
5export function UserProvider({ children }: Props) {
6 const [user, setUser] = useState<User | null>(null);
7
8 function login(user: User) {
9 setUser(user);
10 }
11
12 function logout() {
13 setUser(null);
14 }
15
16 return (
17 <UserContext.Provider value={{ user, login, logout }}>
18 {children}
19 </UserContext.Provider>
20 );
21}

4) Lav en custom hook

I stedet for at bruge useContext direkte i alle komponenter, laver man ofte sin egen hook.

UserContext.tsx

tsx · 9 lines

tsx
1export function useUser() {
2 const context = useContext(UserContext);
3
4 if (!context) {
5 throw new Error("useUser must be used inside UserProvider");
6 }
7
8 return context;
9}

5) Wrap appen med provider

layout.tsx

tsx · 17 lines

tsx
1import { UserProvider } from "@/data/guides/UserContext";
2
3export default function RootLayout({
4 children,
5}: {
6 children: React.ReactNode;
7}) {
8 return (
9 <html lang="da">
10 <body>
11 <UserProvider>
12 {children}
13 </UserProvider>
14 </body>
15 </html>
16 );
17}

6) Brug context i en komponent

Navbar.tsx

tsx · 21 lines

tsx
1"use client";
2
3
4import { useUser } from "@/lib/UserContext";
5
6export default function Navbar() {
7 const { user, logout } = useUser();
8
9 return (
10 <nav>
11 {user ? (
12 <>
13 <span>Hej {user.name}</span>
14 <button onClick={logout}>Log ud</button>
15 </>
16 ) : (
17 <span>Ikke logget ind</span>
18 )}
19 </nav>
20 );
21}

7) Kort opsummering

  • createContext opretter selve contexten.
  • Provider deler data med komponenterne under sig.
  • useContext læser data fra contexten.
  • En custom hook som useUser gør koden mere ryddelig.