Išnaudokite „useRef“ galią „React“ programose. Susipažinkite su įvairiais panaudojimo atvejais, įskaitant tiesioginę DOM prieigą, kintamų reikšmių palaikymą ir funkcinių komponentų veikimo optimizavimą.
React useRef: Kintamų Reikšmių Saugojimo Šablonų Įvaldymas
useRef yra galingas „React“ „hook'as“, suteikiantis būdą išsaugoti reikšmes tarp atvaizdavimų (renders), nesukeliant perrenderinimo, kai tos reikšmės pasikeičia. Jis dažnai siejamas su tiesiogine prieiga prie DOM elementų, tačiau jo galimybės yra kur kas platesnės. Šis išsamus vadovas gilinsis į įvairius useRef panaudojimo atvejus, suteikdamas jums galimybę rašyti efektyvesnį ir lengviau prižiūrimą „React“ kodą.
useRef Supratimas: Daugiau Nei Tik Prieiga Prie DOM
Iš esmės, useRef grąžina kintamą ref objektą, kurio .current savybė yra inicializuojama su perduotu argumentu (initialValue). Grąžintas objektas išliks visą komponento gyvavimo laiką. Svarbiausia, kad .current savybės modifikavimas nesukelia perrenderinimo. Tai yra pagrindinis skirtumas tarp useRef ir useState.
Nors prieiga prie DOM elementų yra dažnas panaudojimo atvejis, useRef puikiai tinka valdyti bet kokią kintamą reikšmę, kuri neturi sukelti perrenderinimo ją atnaujinus. Dėl to jis yra neįkainojamas atliekant tokias užduotis kaip:
- Ankstesnių „prop“ ar būsenos reikšmių saugojimas.
- Skaitiklių ar laikmačių palaikymas.
- Fokusavimo būsenos sekimas nesukeliant perrenderinimo.
- Bet kokios kintamos reikšmės, kuri turi išlikti tarp atvaizdavimų, saugojimas.
Pagrindinis Naudojimas: Prieiga Prie DOM Elementų
Geriausiai žinomas panaudojimo atvejis yra tiesioginė prieiga prie DOM elementų. Tai naudinga scenarijuose, kai reikia imperatyviai sąveikauti su DOM mazgu, pavyzdžiui, fokusuoti įvesties lauką, matuoti jo matmenis ar paleisti animacijas.
Pavyzdys: Įvesties Lauko Fokusavimas
Štai kaip galite naudoti useRef, kad sufokusuotumėte įvesties lauką, kai komponentas yra prijungiamas (mount):
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const inputRef = useRef(null);
useEffect(() => {
// Focus the input field on mount
if (inputRef.current) {
inputRef.current.focus();
}
}, []); // Empty dependency array ensures this runs only once on mount
return (
<input type="text" ref={inputRef} placeholder="Enter text" />
);
}
export default MyComponent;
Paaiškinimas:
- Mes sukuriame „ref“ naudodami
useRef(null). Pradinė reikšmė yranull, nes įvesties elementas dar neegzistuoja, kai komponentas yra pradinai atvaizduojamas. - Mes priskiriame „ref“ įvesties elementui naudodami
refatributą:ref={inputRef}. „React“ automatiškai nustatysinputRef.currentį DOM mazgą, kai įvesties elementas bus prijungtas. - Mes naudojame
useEffectsu tuščiu priklausomybių masyvu ([]), kad užtikrintume, jog efektas bus paleistas tik vieną kartą po to, kai komponentas bus prijungtas. - Efekto viduje mes patikriname, ar
inputRef.currentegzistuoja (kad išvengtume klaidų, jei elementas dar nėra pasiekiamas), ir tada iškviečiameinputRef.current.focus(), kad sufokusuotume įvesties lauką.
Ne Tik DOM Prieiga: Kintamų Reikšmių Valdymas
Tikroji useRef galia slypi jo gebėjime saugoti kintamas reikšmes, kurios išlieka tarp atvaizdavimų, nesukeldamos perrenderinimo. Tai atveria platų galimybių spektrą optimizuojant komponentų elgesį ir valdant būseną funkciniuose komponentuose.
Pavyzdys: Ankstesnių „Prop“ ar Būsenos Reikšmių Saugojimas
Kartais reikia pasiekti ankstesnę „prop“ ar būsenos kintamojo reikšmę. useRef suteikia švarų būdą tai padaryti, nesukeliant nereikalingų perrenderinimų.
import React, { useRef, useEffect } from 'react';
function MyComponent({ value }) {
const previousValue = useRef(value);
useEffect(() => {
// Update the ref's .current property with the current value
previousValue.current = value;
}, [value]); // Effect runs whenever the 'value' prop changes
// Now you can access the previous value using previousValue.current
return (
<div>
Current value: {value}
<br />
Previous value: {previousValue.current}
</div>
);
}
export default MyComponent;
Paaiškinimas:
- Mes inicializuojame „ref“
previousValuesu pradinevalue„prop“ reikšme. - Mes naudojame
useEffect, kad atnaujintumepreviousValue.currentsavybę, kai pasikeičiavalue„prop“. - Komponento viduje dabar galime pasiekti ankstesnę
value„prop“ reikšmę naudodamipreviousValue.current.
Panaudojimo Scenarijaus Pavyzdys: API Atsakymų Pokyčių Sekimas (Tarptautinis Scenarijus)
Įsivaizduokite, kad kuriate prietaisų skydelį, kuriame rodomi valiutų kursai, gaunami iš API. API gali grąžinti kursus skirtingais formatais arba su skirtingu tikslumo lygiu, priklausomai nuo duomenų šaltinio (pvz., Europos Centrinio Banko API prieš Pietryčių Azijos finansų institucijos API). Galite naudoti useRef, kad sektumėte ankstesnį valiutos kursą ir rodytumėte vizualinį indikatorių (pvz., žalią rodyklę aukštyn arba raudoną rodyklę žemyn), ar kursas padidėjo, ar sumažėjo nuo paskutinio atnaujinimo. Tai yra itin svarbu tarptautiniams vartotojams, kurie remiasi šiais kursais priimdami finansinius sprendimus.
Pavyzdys: Skaitiklių ar Laikmačių Palaikymas
useRef puikiai tinka valdyti skaitiklius ar laikmačius, kurie neturi sukelti perrenderinimų. Pavyzdžiui, galite jį naudoti norėdami sekti, kiek kartų buvo paspaustas mygtukas, arba įgyvendinti paprastą laikmatį.
import React, { useRef, useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const clickCount = useRef(0); // Initialize the ref with 0
const handleClick = () => {
clickCount.current++; // Increment the ref's .current property
setCount(clickCount.current); //Increment state which re-renders.
};
return (
<div>
<p>Button clicked: {count} times</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default MyComponent;
Paaiškinimas:
- Mes inicializuojame „ref“
clickCountsu reikšme 0. - Funkcijoje
handleClickmes padidinameclickCount.currentsavybę. Tai nesukelia perrenderinimo. - Mes taip pat atnaujiname būseną 'count', kuri sukelia perrenderinimą.
Pavyzdys: „Debounce“ Funkcijos Įgyvendinimas
„Debouncing“ yra technika, naudojama apriboti funkcijos vykdymo dažnį. Ji dažnai naudojama paieškos įvesties laukuose, siekiant išvengti perteklinių API užklausų, kol vartotojas rašo. useRef galima naudoti laikmačio ID, naudojamo „debounce“ funkcijoje, saugojimui.
import React, { useState, useRef, useEffect } from 'react';
function MyComponent() {
const [searchTerm, setSearchTerm] = useState('');
const [results, setResults] = useState([]);
const timerRef = useRef(null); // Store the timer ID
const handleChange = (event) => {
const newSearchTerm = event.target.value;
setSearchTerm(newSearchTerm);
// Clear the previous timer if it exists
if (timerRef.current) {
clearTimeout(timerRef.current);
}
// Set a new timer
timerRef.current = setTimeout(() => {
// Simulate an API call
fetch(`https://api.example.com/search?q=${newSearchTerm}`)
.then(response => response.json())
.then(data => setResults(data.results));
}, 300); // Debounce for 300 milliseconds
};
return (
<div>
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
/>
<ul>
{results.map(result => (
<li key={result.id}>{result.name}</li>
))}
</ul>
</div>
);
}
export default MyComponent;
Paaiškinimas:
- Mes naudojame
useRef, kad saugotume laikmačio IDtimerRef. - Funkcijoje
handleChangemes išvalome ankstesnį laikmatį (jei jis egzistuoja) naudodamiclearTimeout(timerRef.current). - Tada mes nustatome naują laikmatį naudodami
setTimeoutir išsaugome laikmačio IDtimerRef.current. - API užklausa atliekama tik tada, kai vartotojas nustoja rašyti 300 milisekundžių.
Tarptautinimo Aspektai: Įgyvendinant „debouncing“ su API užklausomis, kurios apima informacijos rodymą skirtingomis kalbomis, užtikrinkite, kad jūsų API palaiko tarptautinimą ir grąžina duomenis vartotojo pageidaujama kalba. Apsvarstykite galimybę naudoti Accept-Language antraštę savo API užklausose.
Pavyzdys: Fokusavimo Būsenos Sekimas Be Perrenderinimų
Galite naudoti useRef, kad sektumėte, ar elementas yra sufokusuotas, nesukeliant perrenderinimų. Tai gali būti naudinga stilizuojant elementus pagal jų fokusavimo būseną arba įgyvendinant pasirinktinę fokusavimo valdymo logiką.
import React, { useRef, useState } from 'react';
function MyComponent() {
const [isFocused, setIsFocused] = useState(false);
const inputRef = useRef(null);
const handleFocus = () => {
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false);
};
return (
<div>
<input
type="text"
ref={inputRef}
onFocus={handleFocus}
onBlur={handleBlur}
/>
<p>Input is focused: {isFocused ? 'Yes' : 'No'}</p>
</div>
);
}
export default MyComponent;
useRef Prieš useState: Tinkamo Įrankio Pasirinkimas
Svarbu suprasti pagrindinius skirtumus tarp useRef ir useState, kad pasirinktumėte tinkamą įrankį konkrečiai užduočiai.
| Savybė | useRef | useState |
|---|---|---|
| Sukelia perrenderinimą | Ne | Taip |
| Paskirtis | Kintamų reikšmių, kurios neturi sukelti perrenderinimų, saugojimas. Prieiga prie DOM elementų. | Būsenos, kuri turi sukelti perrenderinimus, valdymas. |
| Išlikimas | Išlieka tarp perrenderinimų. | Išlieka tarp perrenderinimų, bet reikšmė atnaujinama naudojant „setter“ funkciją. |
Geroji Praktika ir Dažniausios Klaidos
- Nemutuokite būsenos tiesiogiai: Nors
useRefleidžia tiesiogiai mutuoti reikšmes, venkite tiesiogiai mutuoti būsenos kintamuosius, valdomususeState. Visada naudokiteuseStatepateiktą „setter“ funkciją būsenai atnaujinti. - Būkite atidūs šalutiniams poveikiams: Kai naudojate
useRefvaldyti reikšmes, kurios veikia vartotojo sąsają, būkite atidūs galimiems šalutiniams poveikiams. Užtikrinkite, kad jūsų kodas veiktų nuspėjamai ir neįvestų netikėtų klaidų. - Nesiremkite
useRefatvaizdavimo logikai: KadangiuseRefpakeitimai nesukelia perrenderinimų, nesiremkite jo reikšmėmis tiesiogiai, kad nustatytumėte, kas turėtų būti atvaizduojama. NaudokiteuseStatereikšmėms, kurios turi valdyti atvaizdavimo logiką. - Apsvarstykite našumo pasekmes: Nors
useRefgali padėti optimizuoti našumą, išvengiant nereikalingų perrenderinimų, atminkite, kad per didelis kintamų reikšmių naudojimas gali apsunkinti kodo supratimą ir derinimą.
Pažangūs Panaudojimo Atvejai ir Šablonai
Reikšmių Išsaugojimas Tarp Komponentų Egzempliorių
Nors `useRef` išsaugo reikšmes per *vieno* komponento egzemplioriaus atvaizdavimus, kartais reikia, kad reikšmė išliktų ir tarp *skirtingų* to paties komponento egzempliorių. Tam reikalingas šiek tiek kitoks požiūris, dažnai pasitelkiant modulio lygio kintamąjį kartu su `useRef`.
// myComponent.js
let globalCounter = 0; // Module-level variable
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const counterRef = useRef(globalCounter); // Initialize with the global value
useEffect(() => {
// Update the global counter whenever the ref changes
globalCounter = counterRef.current;
}, [counterRef.current]);
const increment = () => {
counterRef.current++;
//No setState needed, so no re-render
};
return (
<div>
<p>Counter: {counterRef.current}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default MyComponent;
Svarbūs Aspektai: Šis šablonas įveda globalų kintamąjį, todėl būkite itin atsargūs dėl galimų šalutinių poveikių ir lenktynių sąlygų (race conditions), ypač sudėtingose programose. Apsvarstykite alternatyvius požiūrius, pavyzdžiui, konteksto teikėjo (context provider) naudojimą, jei reikšmę reikia dalintis tarp kelių komponentų kontroliuojamesniu būdu.
Išvada: Išlaisvinkite useRef Galią
useRef yra universalus įrankis „React“ ekosistemoje, kuris apima daug daugiau nei paprastą prieigą prie DOM elementų. Suprasdami jo gebėjimą saugoti kintamas reikšmes, nesukeliant perrenderinimų, galite optimizuoti savo komponentus, efektyviau valdyti būseną ir kurti našesnes bei lengviau prižiūrimas „React“ programas. Nepamirškite jį naudoti apgalvotai ir visada atsižvelkite į galimus kompromisus tarp našumo ir kodo aiškumo.
Įvaldę šiame vadove aprašytus šablonus, būsite gerai pasirengę išnaudoti visą useRef potencialą savo „React“ projektuose, nesvarbu, ar kuriate paprastą interneto programą, ar sudėtingą įmonės lygio sistemą. Kuriant pasaulinei auditorijai, nepamirškite atsižvelgti į tarptautinimą ir prieinamumą!