Apgūstiet React Context efektīvai stāvokļa pārvaldībai savās lietotnēs. Uzziniet, kad izmantot Context, kā to efektīvi ieviest un izvairīties no biežākajām kļūdām.
React Context: Visaptverošs ceļvedis
React Context ir jaudīga funkcija, kas ļauj koplietot datus starp komponentēm, tieši nenodot "props" cauri katram komponentu koka līmenim. Tas nodrošina veidu, kā noteiktas vērtības padarīt pieejamas visām komponentēm konkrētā apakškokā. Šajā ceļvedī tiek apskatīts, kad un kā efektīvi izmantot React Context, kā arī labākās prakses un biežākās kļūdas, no kurām jāizvairās.
Problēmas izpratne: "Prop Drilling"
Sarežģītās React lietotnēs jūs varat saskarties ar "prop drilling" (īpašību caurduršanas) problēmu. Tas notiek, kad nepieciešams nodot datus no vecāka komponentes dziļi ligzdotai bērna komponentei. Lai to izdarītu, dati ir jānodod caur katru starpnieka komponenti, pat ja šīm komponentēm pašām dati nav nepieciešami. Tas var novest pie:
- Koda pārblīvēšana: Starpnieka komponentes kļūst pārslogotas ar nevajadzīgiem "props".
- Uzturēšanas grūtības: Mainot "prop", ir jāmodificē vairākas komponentes.
- Samazināta lasāmība: Kļūst grūtāk saprast datu plūsmu lietotnē.
Apsveriet šo vienkāršoto piemēru:
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>Laipni lūdzam, {user.name}!
Tēma: {user.theme}</p>
);
}
Šajā piemērā user
objekts tiek nodots caur vairākām komponentēm, lai gan to faktiski izmanto tikai Profile
komponente. Šis ir klasisks "prop drilling" gadījums.
Iepazīstinām ar React Context
React Context nodrošina veidu, kā izvairīties no "prop drilling", padarot datus pieejamus jebkurai komponentei apakškokā, tieši nenodot tos caur "props". Tas sastāv no trīs galvenajām daļām:
- Konteksts (Context): Tas ir konteiners datiem, kurus vēlaties koplietot. Jūs izveidojat kontekstu, izmantojot
React.createContext()
. - Nodrošinātājs (Provider): Šī komponente nodrošina datus kontekstam. Jebkura komponente, kas ietverta Provider, var piekļūt konteksta datiem. Provider pieņem
value
"prop", kas ir dati, kurus vēlaties koplietot. - Patērētājs (Consumer): (Vecāka, retāk sastopama pieeja) Šī komponente abonē kontekstu. Ikreiz, kad konteksta vērtība mainās, Consumer tiks pārrenderēts. Consumer izmanto "render prop" funkciju, lai piekļūtu konteksta vērtībai.
useContext
Hook: (Mūsdienīga pieeja) Šis "hook" ļauj piekļūt konteksta vērtībai tieši funkcionālā komponentē.
Kad lietot React Context
React Context ir īpaši noderīgs, lai koplietotu datus, kas tiek uzskatīti par "globāliem" React komponentu kokam. Tas varētu ietvert:
- Tēma: Koplietot lietotnes tēmu (piem., gaišo vai tumšo režīmu) visās komponentēs. Piemērs: Starptautiska e-komercijas platforma varētu ļaut lietotājiem pārslēgties starp gaišo un tumšo tēmu, lai uzlabotu pieejamību un vizuālās preferences. Konteksts var pārvaldīt un nodrošināt pašreizējo tēmu visām komponentēm.
- Lietotāja autentifikācija: Nodrošināt pašreizējā lietotāja autentifikācijas statusu un profila informāciju. Piemērs: Globāla ziņu vietne var izmantot Context, lai pārvaldītu pieteikušās lietotāja datus (lietotājvārdu, preferences utt.) un padarītu tos pieejamus visā vietnē, nodrošinot personalizētu saturu un funkcijas.
- Valodas preferences: Koplietot pašreizējo valodas iestatījumu internacionalizācijai (i18n). Piemērs: Daudzvalodu lietotne varētu izmantot Context, lai saglabātu pašlaik izvēlēto valodu. Komponentes pēc tam piekļūst šim kontekstam, lai attēlotu saturu pareizajā valodā.
- API klients: Padarīt API klienta instanci pieejamu komponentēm, kurām nepieciešams veikt API izsaukumus.
- Eksperimentu karodziņi (Feature Toggles): Iespējot vai atspējot funkcijas konkrētiem lietotājiem vai grupām. Piemērs: Starptautiska programmatūras kompānija varētu ieviest jaunas funkcijas lietotāju apakškopai noteiktos reģionos, lai pārbaudītu to veiktspēju. Konteksts var nodrošināt šos funkciju karodziņus attiecīgajām komponentēm.
Svarīgi apsvērumi:
- Nav aizstājējs visai stāvokļa pārvaldībai: Context nav pilnvērtīgas stāvokļa pārvaldības bibliotēkas, piemēram, Redux vai Zustand, aizstājējs. Izmantojiet Context datiem, kas ir patiesi globāli un reti mainās. Sarežģītai stāvokļa loģikai un paredzamiem stāvokļa atjauninājumiem bieži vien piemērotāks ir specializēts stāvokļa pārvaldības risinājums. Piemērs: Ja jūsu lietotnei ir jāpārvalda sarežģīts iepirkumu grozs ar daudziem priekšmetiem, daudzumiem un aprēķiniem, stāvokļa pārvaldības bibliotēka varētu būt labāk piemērota nekā paļaušanās tikai uz Context.
- Pārrenderēšana: Kad konteksta vērtība mainās, visas komponentes, kas patērē kontekstu, tiks pārrenderētas. Tas var ietekmēt veiktspēju, ja konteksts tiek bieži atjaunināts vai ja patērējošās komponentes ir sarežģītas. Optimizējiet konteksta izmantošanu, lai samazinātu nevajadzīgu pārrenderēšanu. Piemērs: Reāllaika lietotnē, kas rāda bieži atjauninātas akciju cenas, nevajadzīga to komponenšu pārrenderēšana, kuras ir abonējušas akciju cenu kontekstu, varētu negatīvi ietekmēt veiktspēju. Apsveriet memoizācijas metožu izmantošanu, lai novērstu pārrenderēšanu, kad attiecīgie dati nav mainījušies.
Kā lietot React Context: Praktisks piemērs
Atgriezīsimies pie "prop drilling" piemēra un atrisināsim to, izmantojot React Context.
1. Izveidojiet kontekstu
Vispirms izveidojiet kontekstu, izmantojot React.createContext()
. Šis konteksts glabās lietotāja datus.
// UserContext.js
import React from 'react';
const UserContext = React.createContext(null); // Noklusējuma vērtība var būt null vai sākotnējs lietotāja objekts
export default UserContext;
2. Izveidojiet nodrošinātāju (Provider)
Pēc tam ietiniet savas lietotnes sakni (vai attiecīgo apakškoku) ar UserContext.Provider
. Nododiet user
objektu kā value
"prop" nodrošinātājam.
// 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. Patērējiet kontekstu
Tagad Profile
komponente var piekļūt user
datiem tieši no konteksta, izmantojot useContext
"hook". Vairs nekāda "prop drilling"!
// Profile.js
import React, { useContext } from 'react';
import UserContext from './UserContext';
function Profile() {
const user = useContext(UserContext);
return (
<p>Laipni lūdzam, {user.name}!
Tēma: {user.theme}</p>
);
}
export default Profile;
Starpnieka komponentēm (Layout
, Header
un Navigation
) vairs nav nepieciešams saņemt user
"prop".
// 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;
Papildu lietojums un labākās prakses
1. Konteksta apvienošana ar useReducer
Sarežģītākai stāvokļa pārvaldībai varat apvienot React Context ar useReducer
"hook". Tas ļauj pārvaldīt stāvokļa atjauninājumus paredzamākā un uzturējamākā veidā. Konteksts nodrošina stāvokli, un "reducer" apstrādā stāvokļa pārejas, pamatojoties uz nosūtītajām darbībām.
// 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' })}> Pārslēgt tēmu (Pašreizējā: {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. Vairāki konteksti
Jūs varat izmantot vairākus kontekstus savā lietotnē, ja jums ir jāpārvalda dažāda veida globālie dati. Tas palīdz saglabāt atdalītas bažas (concerns) un uzlabo koda organizāciju. Piemēram, jums varētu būt UserContext
lietotāja autentifikācijai un ThemeContext
lietotnes tēmas pārvaldībai.
3. Veiktspējas optimizēšana
Kā minēts iepriekš, konteksta izmaiņas var izraisīt patērējošo komponenšu pārrenderēšanu. Lai optimizētu veiktspēju, apsveriet sekojošo:
- Memoizācija: Izmantojiet
React.memo
, lai novērstu nevajadzīgu komponenšu pārrenderēšanu. - Stabilas konteksta vērtības: Pārliecinieties, ka
value
"prop", kas nodots nodrošinātājam, ir stabila atsauce. Ja vērtība ir jauns objekts vai masīvs katrā renderēšanas reizē, tas izraisīs nevajadzīgu pārrenderēšanu. - Selektīvi atjauninājumi: Atjauniniet konteksta vērtību tikai tad, kad tai patiešām ir jāmainās.
4. Pielāgotu "hook" izmantošana piekļuvei kontekstam
Izveidojiet pielāgotus "hooks", lai iekapsulētu loģiku piekļuvei un konteksta vērtību atjaunināšanai. Tas uzlabo koda lasāmību un uzturēšanu. Piemēram:
// useTheme.js import { useContext } from 'react'; import { ThemeContext } from './ThemeContext'; function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme ir jāizmanto ThemeProvider ietvaros'); } return context; } export default useTheme;
// MyComponent.js import React from 'react'; import useTheme from './useTheme'; function MyComponent() { const { theme, dispatch } = useTheme(); return ( <div> Pašreizējā tēma: {theme} <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}> Pārslēgt tēmu </button> </div> ); } export default MyComponent;
Biežākās kļūdas, no kurām jāizvairās
- Pārmērīga konteksta izmantošana: Neizmantojiet Context visam. Tas ir vislabāk piemērots datiem, kas ir patiesi globāli.
- Sarežģīti atjauninājumi: Izvairieties no sarežģītu aprēķinu vai blakusefektu veikšanas tieši konteksta nodrošinātājā. Izmantojiet "reducer" vai citu stāvokļa pārvaldības tehniku, lai apstrādātu šīs operācijas.
- Veiktspējas ignorēšana: Esiet uzmanīgi attiecībā uz veiktspējas ietekmi, izmantojot Context. Optimizējiet savu kodu, lai samazinātu nevajadzīgu pārrenderēšanu.
- Noklusējuma vērtības nenodrošināšana: Lai gan tas nav obligāti, noklusējuma vērtības nodrošināšana
React.createContext()
var palīdzēt novērst kļūdas, ja komponente mēģina patērēt kontekstu ārpus nodrošinātāja.
Alternatīvas React Context
Lai gan React Context ir vērtīgs rīks, tas ne vienmēr ir labākais risinājums. Apsveriet šīs alternatīvas:
- Prop Drilling (dažreiz): Vienkāršos gadījumos, kad dati ir nepieciešami tikai dažām komponentēm, "prop drilling" var būt vienkāršāks un efektīvāks nekā Context izmantošana.
- Stāvokļa pārvaldības bibliotēkas (Redux, Zustand, MobX): Sarežģītām lietotnēm ar sarežģītu stāvokļa loģiku specializēta stāvokļa pārvaldības bibliotēka bieži ir labāka izvēle.
- Komponentu kompozīcija: Izmantojiet komponentu kompozīciju, lai nodotu datus caur komponentu koku kontrolētākā un skaidrākā veidā.
Noslēgums
React Context ir jaudīga funkcija datu koplietošanai starp komponentēm bez "prop drilling". Izpratne par to, kad un kā to efektīvi izmantot, ir būtiska, lai veidotu uzturējamas un veiktspējīgas React lietotnes. Ievērojot šajā ceļvedī izklāstītās labākās prakses un izvairoties no biežākajām kļūdām, jūs varat izmantot React Context, lai uzlabotu savu kodu un radītu labāku lietotāja pieredzi. Atcerieties novērtēt savas specifiskās vajadzības un apsvērt alternatīvas, pirms izlemjat, vai izmantot Context.