Įvaldykite React Context efektyviam būsenos valdymui savo programose. Sužinokite, kada naudoti Context, kaip jį efektyviai įdiegti ir išvengti dažniausių klaidų.
React Context: Išsamus vadovas
React Context yra galinga funkcija, leidžianti dalytis duomenimis tarp komponentų, aiškiai neperduodant rekvizitų per kiekvieną komponentų medžio lygį. Tai suteikia galimybę padaryti tam tikras reikšmes prieinamas visiems komponentams konkrečiame po medyje. Šis vadovas nagrinėja, kada ir kaip efektyviai naudoti React Context, kartu su geriausia praktika ir bendromis klaidomis, kurių reikia vengti.
Problemos supratimas: Rekvizitų gręžimas
Sudėtingose React programose galite susidurti su „rekvizitų gręžimo“ problema. Tai atsitinka, kai reikia perduoti duomenis iš tėvinio komponento giliai į įdėtąjį vaiko komponentą. Norėdami tai padaryti, turite perduoti duomenis per kiekvieną tarpinį komponentą, net jei tiems komponentams nereikia pačių duomenų. Tai gali sukelti:
- Kodo netvarka: Tarpiniai komponentai tampa perpildyti nereikalingais rekvizitais.
- Priežiūros sunkumai: Keičiant rekvizitą, reikia modifikuoti kelis komponentus.
- Sumažintas skaitomumas: Sunkiau suprasti duomenų srautą per programą.
Apsvarstykite šį supaprastintą pavyzdį:
function App() {
const user = { name: 'Alice', theme: 'dark' };
return (
<Layout user={user} />
);
}
function Layout({ user }) {
return (
<Header user={user} />
);
}
function Header({ user }) {
return (
<Navigation user={user} />
);
}
function Navigation({ user }) {
return (
<Profile user={user} />
);
}
function Profile({ user }) {
return (
<p>Sveiki, {user.name}!
Theme: {user.theme}</p>
);
}
Šiame pavyzdyje objektas user
perduodamas per kelis komponentus, nors tik Profile
komponentas iš tikrųjų jį naudoja. Tai klasikinis rekvizitų gręžimo atvejis.
React Context įvedimas
React Context suteikia galimybę išvengti rekvizitų gręžimo, padarydamas duomenis prieinamus bet kuriam komponentui po medyje, aiškiai neperduodant jų per rekvizitus. Jį sudaro trys pagrindinės dalys:
- Kontekstas: Tai konteineris duomenims, kuriais norite dalytis. Kontekstas sukuriamas naudojant
React.createContext()
. - Tiekėjas: Šis komponentas pateikia duomenis kontekstui. Bet kuris komponentas, apvyniotas Provider, gali pasiekti konteksto duomenis. Tiekėjas priima
value
rekvizitą, kuris yra duomenys, kuriais norite dalytis. - Vartotojas: (Senas, rečiau naudojamas) Šis komponentas prenumeruoja kontekstą. Kai pasikeičia konteksto reikšmė, Vartotojas bus pakartotinai atvaizduotas. Vartotojas naudoja atvaizdavimo rekvizito funkciją, kad pasiektų konteksto reikšmę.
useContext
Kablys: (Šiuolaikinis požiūris) Šis kabliukas leidžia pasiekti konteksto reikšmę tiesiogiai funkciniame komponente.
Kada naudoti React Context
React Context ypač naudingas dalijantis duomenimis, kurie laikomi „globaliais“ React komponentų medžiui. Tai gali būti:
- Tema: Programos temos (pvz., šviesus arba tamsus režimas) bendrinimas visuose komponentuose. Pavyzdys: Tarptautinė e. prekybos platforma gali leisti vartotojams perjungti šviesią ir tamsią temą, kad pagerintų prieinamumą ir vizualinius pageidavimus. Kontekstas gali valdyti ir teikti esamą temą visiems komponentams.
- Vartotojo autentifikavimas: Esamo vartotojo autentifikavimo būsenos ir profilio informacijos pateikimas. Pavyzdys: Pasaulinė naujienų svetainė gali naudoti Kontekstą norėdama valdyti prisijungusio vartotojo duomenis (vartotojo vardas, nuostatos ir kt.) ir padaryti juos prieinamus visoje svetainėje, įgalindama individualų turinį ir funkcijas.
- Kalbos nuostatos: Dabartinės kalbos nustatymo bendrinimas tarptautinimui (i18n). Pavyzdys: Daugiakalbė programa gali naudoti Kontekstą, kad saugotų šiuo metu pasirinktą kalbą. Tada komponentai pasiekia šį kontekstą, kad turinys būtų rodomas teisinga kalba.
- API klientas: API kliento egzemplioriaus pateikimas komponentams, kuriems reikia skambinti API.
- Eksperimentiniai žymekliai (funkcijų perjungimai): Įjungti arba išjungti funkcijas konkretiems vartotojams ar grupėms. Pavyzdys: Tarptautinė programinės įrangos įmonė gali pirmiausia diegti naujas funkcijas poaibiui vartotojų tam tikruose regionuose, kad išbandytų jų našumą. Kontekstas gali pateikti šiuos funkcijų žymeklius atitinkamiems komponentams.
Svarbūs svarstymai:
- Ne visiškas būsenos valdymo pakeitimas: Kontekstas nepakeičia pilnos būsenos valdymo bibliotekos, pvz., Redux arba Zustand. Naudokite Kontekstą duomenims, kurie yra tikrai globalūs ir retai keičiasi. Norint sudėtingos būsenos logikos ir nuspėjamų būsenos atnaujinimų, dažnai tinkamesnis yra specialus būsenos valdymo sprendimas. Pavyzdys: Jei jūsų programa apima sudėtingo pirkinių krepšelio, turinčio daugybę prekių, kiekių ir skaičiavimų, valdymą, būsenos valdymo biblioteka gali būti geresnė nei vien tik Konteksto naudojimas.
- Pakartotinis atvaizdavimas: Kai pasikeičia konteksto reikšmė, visi komponentai, kurie naudoja kontekstą, bus pakartotinai atvaizduoti. Tai gali turėti įtakos našumui, jei kontekstas atnaujinamas dažnai arba jei naudojami komponentai yra sudėtingi. Optimizuokite savo konteksto naudojimą, kad sumažintumėte nereikalingą pakartotinį atvaizdavimą. Pavyzdys: Realaus laiko programoje, kurioje dažnai atnaujinamos akcijų kainos, nereikalingas komponentų, kurie yra užsiprenumeravę akcijų kainos kontekstą, pakartotinis atvaizdavimas gali neigiamai paveikti našumą. Apsvarstykite galimybę naudoti memorizavimo metodus, kad išvengtumėte pakartotinio atvaizdavimo, kai atitinkami duomenys nepasikeitė.
Kaip naudoti React Context: praktinis pavyzdys
Peržiūrėkime rekvizitų gręžimo pavyzdį ir išspręskime jį naudodami React Context.
1. Sukurkite kontekstą
Pirmiausia sukurkite kontekstą naudodami React.createContext()
. Šis kontekstas saugos vartotojo duomenis.
// UserContext.js
import React from 'react';
const UserContext = React.createContext(null); // Numatytąją reikšmę galima nustatyti į null arba pradinį vartotojo objektą
export default UserContext;
2. Sukurkite tiekėją
Toliau apvyniokite savo programos šaknį (arba atitinkamą po medį) su UserContext.Provider
. Perduokite objektą user
kaip value
rekvizitą tiekėjui.
// App.js
import React from 'react';
import UserContext from './UserContext';
import Layout from './Layout';
function App() {
const user = { name: 'Alice', theme: 'dark' };
return (
<UserContext.Provider value={user}>
<Layout />
</UserContext.Provider>
);
}
export default App;
3. Naudokite kontekstą
Dabar komponentas Profile
gali pasiekti duomenis user
tiesiogiai iš konteksto naudodamas kabliuką useContext
. Daugiau jokio rekvizitų gręžimo!
// Profile.js
import React, { useContext } from 'react';
import UserContext from './UserContext';
function Profile() {
const user = useContext(UserContext);
return (
<p>Sveiki, {user.name}!
Theme: {user.theme}</p>
);
}
export default Profile;
Tarpiniams komponentams (Layout
, Header
ir Navigation
) nebereikia gauti rekvizito user
.
// Layout.js, Header.js, Navigation.js
import React from 'react';
function Layout({ children }) {
return (
<div>
<Header />
<main>{children}</main>
</div>
);
}
function Header() {
return (<Navigation />);
}
function Navigation() {
return (<Profile />);
}
export default Layout;
Išplėstinis naudojimas ir geriausia praktika
1. Konteksto derinimas su useReducer
Norėdami geriau valdyti būseną, galite derinti React Context su kabliuku useReducer
. Tai leidžia valdyti būsenos atnaujinimus nuspėjamesniu ir prižiūrimu būdu. Kontekstas pateikia būseną, o reduktorius apdoroja būsenos perėjimus, pagrįstus išsiųstais veiksmais.
// ThemeContext.js import React, { createContext, useReducer } from 'react'; const ThemeContext = createContext(); const initialState = { theme: 'light' }; const themeReducer = (state, action) => { switch (action.type) { case 'TOGGLE_THEME': return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' }; default: return state; } }; function ThemeProvider({ children }) { const [state, dispatch] = useReducer(themeReducer, initialState); return ( <ThemeContext.Provider value={{ ...state, dispatch }}> {children} </ThemeContext.Provider> ); } export { ThemeContext, ThemeProvider };
// ThemeToggle.js import React, { useContext } from 'react'; import { ThemeContext } from './ThemeContext'; function ThemeToggle() { const { theme, dispatch } = useContext(ThemeContext); return ( <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}> Perjungti temą (Dabartinė: {theme}) </button> ); } export default ThemeToggle;
// App.js import React from 'react'; import { ThemeProvider } from './ThemeContext'; import ThemeToggle from './ThemeToggle'; function App() { return ( <ThemeProvider> <div> <ThemeToggle /> </div> </ThemeProvider> ); } export default App;
2. Keli kontekstai
Galite naudoti kelis kontekstus savo programoje, jei norite valdyti skirtingus globalių duomenų tipus. Tai padeda išlaikyti atskirus rūpesčius ir pagerina kodo organizavimą. Pavyzdžiui, galite turėti UserContext
vartotojo autentifikavimui ir ThemeContext
programos temai valdyti.
3. Našumo optimizavimas
Kaip minėta anksčiau, konteksto pakeitimai gali sukelti pakartotinį atvaizdavimą naudojamuose komponentuose. Norėdami optimizuoti našumą, apsvarstykite šiuos dalykus:
- Memorizavimas: Naudokite
React.memo
, kad komponentai nebūtų nereikalingai pakartotinai atvaizduojami. - Stabilios konteksto reikšmės: Užtikrinkite, kad
value
rekvizitas, perduodamas tiekėjui, būtų stabilus. Jei reikšmė yra naujas objektas arba masyvas kiekviename atvaizdavime, tai sukels nereikalingą pakartotinį atvaizdavimą. - Selektiniai atnaujinimai: Atnaujinkite konteksto reikšmę tik tada, kai ją iš tikrųjų reikia pakeisti.
4. Pasirinktinių kabliukų naudojimas konteksto prieigai
Sukurkite pasirinktinius kabliukus, kad įkapsuliuotumėte logiką, skirtą prieigai prie konteksto reikšmių ir jų atnaujinimui. Tai pagerina kodo skaitomumą ir prižiūrimumą. Pavyzdžiui:
// useTheme.js import { useContext } from 'react'; import { ThemeContext } from './ThemeContext'; function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within a ThemeProvider'); } return context; } export default useTheme;
// MyComponent.js import React from 'react'; import useTheme from './useTheme'; function MyComponent() { const { theme, dispatch } = useTheme(); return ( <div> Dabartinė tema: {theme} <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}> Perjungti temą </button> </div> ); } export default MyComponent;
Bendros klaidos, kurių reikia vengti
- Per didelis konteksto naudojimas: Nenaudokite Konteksto viskam. Jis geriausiai tinka duomenims, kurie yra tikrai globalūs.
- Sudėtingi atnaujinimai: Venkite sudėtingų skaičiavimų ar šalutinių efektų tiesiogiai konteksto tiekėjui. Naudokite reduktorių ar kitą būsenos valdymo metodą šioms operacijoms apdoroti.
- Nepaisoma našumo: Būkite dėmesingi našumo pasekmėms naudodami Kontekstą. Optimizuokite kodą, kad sumažintumėte nereikalingą pakartotinį atvaizdavimą.
- Nepateikiama numatytoji reikšmė: Nors ir neprivaloma, numatytosios reikšmės pateikimas
React.createContext()
gali padėti išvengti klaidų, jei komponentas bando naudoti kontekstą už tiekėjo ribų.
React Context alternatyvos
Nors React Context yra vertingas įrankis, jis ne visada yra geriausias sprendimas. Apsvarstykite šias alternatyvas:
- Rekvizitų gręžimas (kartais): Paprastais atvejais, kai duomenys reikalingi tik keliems komponentams, rekvizitų gręžimas gali būti paprastesnis ir efektyvesnis nei naudojant Kontekstą.
- Būsenos valdymo bibliotekos (Redux, Zustand, MobX): Sudėtingoms programoms su sudėtinga būsenos logika specializuota būsenos valdymo biblioteka dažnai yra geresnis pasirinkimas.
- Komponentų sudėtis: Naudokite komponentų sudėtį norėdami perduoti duomenis per komponentų medį labiau kontroliuojamu ir aiškiu būdu.
Išvada
React Context yra galinga funkcija, skirta dalytis duomenimis tarp komponentų be rekvizitų gręžimo. Norint sukurti prižiūrimas ir našias React programas, būtina suprasti, kada ir kaip ją efektyviai naudoti. Laikydamiesi šiame vadove aprašytos geriausios praktikos ir vengdami dažniausių klaidų, galite panaudoti React Context, kad pagerintumėte savo kodą ir sukurtumėte geresnę vartotojo patirtį. Nepamirškite įvertinti savo konkrečių poreikių ir apsvarstyti alternatyvas prieš nuspręsdami, ar naudoti Context.