Išsamus „React“ „useContext“ kabliuko vadovas, apimantis konteksto naudojimo modelius ir pažangias našumo optimizavimo technikas, skirtas kurti mastelio keitimui pritaikytas ir efektyvias programas.
React useContext: Konteksto naudojimo įsisavinimas ir našumo optimizavimas
„React“ Context API suteikia galingą būdą dalytis duomenimis tarp komponentų, aiškiai neperduodant „props“ per kiekvieną komponentų medžio lygį. useContext kabliukas supaprastina konteksto reikšmių naudojimą, todėl lengviau pasiekti ir naudoti bendrus duomenis funkciniuose komponentuose. Tačiau netinkamas useContext naudojimas gali sukelti našumo problemų, ypač didelėse ir sudėtingose programose. Šiame vadove nagrinėjamos geriausios konteksto naudojimo praktikos ir pateikiamos pažangios optimizavimo technikos, siekiant užtikrinti efektyvias ir mastelį keisti galinčias „React“ programas.
„React“ Context API supratimas
Prieš gilinantis į useContext, trumpai apžvelkime pagrindines Context API sąvokas. Context API susideda iš trijų pagrindinių dalių:
- Kontekstas (Context): Bendrų duomenų talpykla. Kontekstą sukuriate naudodami
React.createContext(). - Teikėjas (Provider): Komponentas, kuris suteikia konteksto reikšmę savo palikuonims. Visi komponentai, apgaubti teikėju, gali pasiekti konteksto reikšmę.
- Vartotojas (Consumer): Komponentas, kuris prenumeruoja konteksto reikšmę ir pervaizduojamas, kai konteksto reikšmė pasikeičia.
useContextkabliukas yra modernus būdas naudoti kontekstą funkciniuose komponentuose.
„useContext“ kabliuko pristatymas
useContext kabliukas yra „React“ kabliukas, leidžiantis funkciniams komponentams prenumeruoti kontekstą. Jis priima konteksto objektą (reikšmę, kurią grąžina React.createContext()) ir grąžina dabartinę to konteksto reikšmę. Kai konteksto reikšmė pasikeičia, komponentas pervaizduojamas.
Štai pagrindinis pavyzdys:
Pagrindinis pavyzdys
Tarkime, turite temos kontekstą:
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext('light');
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
const value = {
theme,
toggleTheme,
};
return (
{children}
);
}
function ThemedComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
Current Theme: {theme}
);
}
function App() {
return (
);
}
export default App;
Šiame pavyzdyje:
ThemeContextyra sukurtas naudojantReact.createContext('light'). Numatytoji reikšmė yra „light“.ThemeProvidersuteikia temos reikšmę irtoggleThemefunkciją savo vaikams.ThemedComponentnaudojauseContext(ThemeContext), kad pasiektų dabartinę temą irtoggleThemefunkciją.
Dažniausios klaidos ir našumo problemos
Nors useContext supaprastina konteksto naudojimą, jis taip pat gali sukelti našumo problemų, jei nėra naudojamas atsargiai. Štai keletas dažniausiai pasitaikančių klaidų:
- Nereikalingi pervaizdavimai: Bet kuris komponentas, naudojantis
useContext, bus pervaizduotas, kai tik pasikeis konteksto reikšmė, net jei komponentas iš tikrųjų nenaudoja tos konkrečios konteksto reikšmės dalies, kuri pasikeitė. Tai gali sukelti nereikalingus pervaizdavimus ir našumo problemas, ypač didelėse programose su dažnai atnaujinamomis konteksto reikšmėmis. - Didelės konteksto reikšmės: Jei konteksto reikšmė yra didelis objektas, bet koks pakeitimas bet kurioje to objekto savybėje sukels visų jį naudojančių komponentų pervaizdavimą.
- Dažni atnaujinimai: Jei konteksto reikšmė atnaujinama dažnai, tai gali sukelti pervaizdavimų kaskadą visame komponentų medyje, o tai neigiamai paveiks našumą.
Našumo optimizavimo technikos
Norėdami sumažinti šias našumo problemas, apsvarstykite šias optimizavimo technikas:
1. Konteksto skaidymas
Užuot dėdami visus susijusius duomenis į vieną kontekstą, padalinkite kontekstą į mažesnius, smulkesnius kontekstus. Tai sumažina komponentų, kurie pervaizduojami, kai pasikeičia tam tikra duomenų dalis, skaičių.
Pavyzdys:
Užuot turėję vieną UserContext, kuriame yra ir vartotojo profilio informacija, ir vartotojo nustatymai, sukurkite atskirus kontekstus kiekvienam:
import React, { createContext, useContext, useState } from 'react';
const UserProfileContext = createContext(null);
const UserSettingsContext = createContext(null);
function UserProfileProvider({ children }) {
const [profile, setProfile] = useState({
name: 'John Doe',
email: 'john.doe@example.com',
});
const updateProfile = (newProfile) => {
setProfile(newProfile);
};
const value = {
profile,
updateProfile,
};
return (
{children}
);
}
function UserSettingsProvider({ children }) {
const [settings, setSettings] = useState({
notificationsEnabled: true,
theme: 'light',
});
const updateSettings = (newSettings) => {
setSettings(newSettings);
};
const value = {
settings,
updateSettings,
};
return (
{children}
);
}
function ProfileComponent() {
const { profile } = useContext(UserProfileContext);
return (
Name: {profile?.name}
Email: {profile?.email}
);
}
function SettingsComponent() {
const { settings } = useContext(UserSettingsContext);
return (
Notifications: {settings?.notificationsEnabled ? 'Enabled' : 'Disabled'}
Theme: {settings?.theme}
);
}
function App() {
return (
);
}
export default App;
Dabar vartotojo profilio pakeitimai pervaizduos tik tuos komponentus, kurie naudoja UserProfileContext, o vartotojo nustatymų pakeitimai pervaizduos tik tuos komponentus, kurie naudoja UserSettingsContext.
2. Memoizacija su React.memo
Apgaubkite komponentus, kurie naudoja kontekstą, su React.memo. React.memo yra aukštesnės eilės komponentas, kuris memoizuoja funkcinį komponentą. Jis apsaugo nuo pervaizdavimų, jei komponento „props“ nepasikeitė. Kartu su konteksto skaidymu tai gali žymiai sumažinti nereikalingų pervaizdavimų skaičių.
Pavyzdys:
import React, { useContext } from 'react';
const MyContext = React.createContext(null);
const MyComponent = React.memo(function MyComponent() {
const { value } = useContext(MyContext);
console.log('MyComponent rendered');
return (
Value: {value}
);
});
export default MyComponent;
Šiame pavyzdyje MyComponent bus pervaizduotas tik tada, kai pasikeis value reikšmė MyContext.
3. useMemo ir useCallback
Naudokite useMemo ir useCallback, kad memoizuotumėte reikšmes ir funkcijas, kurios perduodamos kaip konteksto reikšmės. Tai užtikrina, kad konteksto reikšmė pasikeis tik tada, kai pasikeis pagrindinės priklausomybės, taip išvengiant nereikalingų komponentų pervaizdavimų.
Pavyzdys:
import React, { createContext, useState, useMemo, useCallback, useContext } from 'react';
const MyContext = createContext(null);
function MyProvider({ children }) {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
const contextValue = useMemo(() => ({
count,
increment,
}), [count, increment]);
return (
{children}
);
}
function MyComponent() {
const { count, increment } = useContext(MyContext);
console.log('MyComponent rendered');
return (
Count: {count}
);
}
function App() {
return (
);
}
export default App;
Šiame pavyzdyje:
useCallbackmemoizuojaincrementfunkciją, užtikrindama, kad ji pasikeis tik tada, kai pasikeis jos priklausomybės (šiuo atveju ji neturi priklausomybių, todėl yra memoizuojama neribotai).useMemomemoizuoja konteksto reikšmę, užtikrindama, kad ji pasikeis tik tada, kai pasikeiscountarbaincrementfunkcija.
4. Selektoriai
Įdiekite selektorius, kad iš konteksto reikšmės išgautumėte tik reikiamus duomenis komponentuose. Tai sumažina nereikalingų pervaizdavimų tikimybę, užtikrinant, kad komponentai būtų pervaizduojami tik tada, kai pasikeičia konkretūs duomenys, nuo kurių jie priklauso.
Pavyzdys:
import React, { createContext, useContext } from 'react';
const MyContext = createContext(null);
const selectCount = (contextValue) => contextValue.count;
function MyComponent() {
const contextValue = useContext(MyContext);
const count = selectCount(contextValue);
console.log('MyComponent rendered');
return (
Count: {count}
);
}
export default MyComponent;
Nors šis pavyzdys yra supaprastintas, realaus pasaulio scenarijuose selektoriai gali būti sudėtingesni ir našesni, ypač dirbant su didelėmis konteksto reikšmėmis.
5. Nekintamos duomenų struktūros
Nekintamų duomenų struktūrų naudojimas užtikrina, kad konteksto reikšmės pakeitimai sukuria naujus objektus, o ne modifikuoja esamus. Tai palengvina „React“ galimybę aptikti pakeitimus ir optimizuoti pervaizdavimus. Bibliotekos, tokios kaip Immutable.js, gali būti naudingos valdant nekintamas duomenų struktūras.
Pavyzdys:
import React, { createContext, useState, useMemo, useContext } from 'react';
import { Map } from 'immutable';
const MyContext = createContext(Map());
function MyProvider({ children }) {
const [data, setData] = useState(Map({
count: 0,
name: 'Initial Name',
}));
const increment = () => {
setData(prevData => prevData.set('count', prevData.get('count') + 1));
};
const updateName = (newName) => {
setData(prevData => prevData.set('name', newName));
};
const contextValue = useMemo(() => ({
data,
increment,
updateName,
}), [data]);
return (
{children}
);
}
function MyComponent() {
const contextValue = useContext(MyContext);
const count = contextValue.get('count');
console.log('MyComponent rendered');
return (
Count: {count}
);
}
function App() {
return (
);
}
export default App;
Šis pavyzdys naudoja Immutable.js konteksto duomenims valdyti, užtikrinant, kad kiekvienas atnaujinimas sukuria naują nekintamą Map, o tai padeda „React“ efektyviau optimizuoti pervaizdavimus.
Realaus pasaulio pavyzdžiai ir naudojimo atvejai
Context API ir useContext yra plačiai naudojami įvairiuose realaus pasaulio scenarijuose:
- Temų valdymas: Kaip parodyta ankstesniame pavyzdyje, temų (šviesus/tamsus režimas) valdymas visoje programoje.
- Autentifikacija: Vartotojo autentifikacijos būsenos ir vartotojo duomenų teikimas komponentams, kuriems to reikia. Pavyzdžiui, globalus autentifikacijos kontekstas gali valdyti vartotojo prisijungimą, atsijungimą ir vartotojo profilio duomenis, todėl jie tampa prieinami visoje programoje be „prop drilling“.
- Kalbos/lokalės nustatymai: Dabartinės kalbos ar lokalės nustatymų dalijimasis visoje programoje internacionalizacijai (i18n) ir lokalizacijai (l10n). Tai leidžia komponentams rodyti turinį vartotojo pasirinkta kalba.
- Visuotinė konfigūracija: Visuotinių konfigūracijos nustatymų, tokių kaip API galiniai taškai ar funkcijų vėliavėlės, dalijimasis. Tai gali būti naudojama dinamiškai koreguoti programos elgseną pagal konfigūracijos nustatymus.
- Pirkinių krepšelis: Pirkinių krepšelio būsenos valdymas ir prieigos prie krepšelio prekių bei operacijų suteikimas komponentams visoje el. prekybos programoje.
Pavyzdys: internacionalizacija (i18n)
Iliustruokime paprastą Context API naudojimo internacionalizacijai pavyzdį:
import React, { createContext, useState, useContext, useMemo } from 'react';
const LanguageContext = createContext({
locale: 'en',
messages: {},
});
const translations = {
en: {
greeting: 'Hello',
description: 'Welcome to our website!',
},
fr: {
greeting: 'Bonjour',
description: 'Bienvenue sur notre site web !',
},
es: {
greeting: 'Hola',
description: '¡Bienvenido a nuestro sitio web!',
},
};
function LanguageProvider({ children }) {
const [locale, setLocale] = useState('en');
const setLanguage = (newLocale) => {
setLocale(newLocale);
};
const messages = useMemo(() => translations[locale] || translations['en'], [locale]);
const contextValue = useMemo(() => ({
locale,
messages,
setLanguage,
}), [locale, messages]);
return (
{children}
);
}
function Greeting() {
const { messages } = useContext(LanguageContext);
return (
{messages.greeting}
);
}
function Description() {
const { messages } = useContext(LanguageContext);
return (
{messages.description}
);
}
function LanguageSwitcher() {
const { setLanguage } = useContext(LanguageContext);
return (
);
}
function App() {
return (
);
}
export default App;
Šiame pavyzdyje:
LanguageContextsuteikia dabartinę lokalę ir pranešimus.LanguageProvidervaldo lokalės būseną ir suteikia konteksto reikšmę.GreetingirDescriptionkomponentai naudoja kontekstą, kad rodytų išverstą tekstą.LanguageSwitcherkomponentas leidžia vartotojams pakeisti kalbą.
„useContext“ alternatyvos
Nors useContext yra galingas įrankis, jis ne visada yra geriausias sprendimas kiekvienam būsenos valdymo scenarijui. Štai keletas alternatyvų, kurias verta apsvarstyti:
- Redux: Nuspėjama būsenos talpykla JavaScript programoms. Redux yra populiarus pasirinkimas valdant sudėtingą programos būseną, ypač didesnėse programose.
- MobX: Paprastas, mastelį keisti galintis būsenos valdymo sprendimas. MobX naudoja stebimus duomenis ir automatinį reaktyvumą būsenai valdyti.
- Recoil: Būsenos valdymo biblioteka „React“, kuri naudoja atomus ir selektorius būsenai valdyti. Recoil yra sukurta taip, kad būtų smulkesnė ir efektyvesnė nei Redux ar MobX.
- Zustand: Mažas, greitas ir mastelį keisti galintis būsenos valdymo sprendimas, naudojantis supaprastintus flux principus.
- Jotai: Primityvus ir lankstus būsenos valdymas „React“ su atominiu modeliu.
- Prop Drilling: Paprastesniais atvejais, kai komponentų medis yra negilus, „prop drilling“ gali būti tinkamas variantas. Tai apima „props“ perdavimą per kelis komponentų medžio lygius.
Būsenos valdymo sprendimo pasirinkimas priklauso nuo konkrečių jūsų programos poreikių. Priimdami sprendimą, atsižvelkite į savo programos sudėtingumą, komandos dydį ir našumo reikalavimus.
Išvada
„React“ useContext kabliukas suteikia patogų ir efektyvų būdą dalytis duomenimis tarp komponentų. Suprasdami galimas našumo problemas ir taikydami šiame vadove aprašytas optimizavimo technikas, galite išnaudoti useContext galią kurdami mastelį keisti galinčias ir našias „React“ programas. Nepamirškite skaidyti kontekstų, kai tai tikslinga, memoizuoti komponentus su React.memo, naudoti useMemo ir useCallback konteksto reikšmėms, įdiegti selektorius ir apsvarstyti galimybę naudoti nekintamas duomenų struktūras, kad sumažintumėte nereikalingus pervaizdavimus ir optimizuotumėte savo programos našumą.
Visada profiliuokite savo programos našumą, kad nustatytumėte ir pašalintumėte bet kokias su konteksto naudojimu susijusias problemas. Laikydamiesi šių geriausių praktikų, galite užtikrinti, kad jūsų useContext naudojimas prisidės prie sklandžios ir efektyvios vartotojo patirties.