Opi hallitsemaan Reactin createRef imperatiivista DOM- ja komponentti-instanssimanipulaatiota varten. Ymmärrä, milloin ja miten sitä käytetään tehokkaasti luokkakomponenteissa fokuksen, median ja kolmannen osapuolen integraatioiden hallintaan.
React createRef: Kattava opas suoraan komponentti- ja DOM-elementtivuorovaikutukseen
Nykyaikaisen web-kehityksen laajassa ja usein monimutkaisessa maisemassa React on noussut hallitsevaksi voimaksi, jota arvostetaan pääasiassa sen deklaratiivisen lähestymistavan vuoksi käyttöliittymien rakentamisessa. Tämä paradigma kannustaa kehittäjiä kuvailemaan, miltä heidän käyttöliittymänsä tulisi näyttää datan perusteella, sen sijaan että he määrittelisivät, miten kyseinen visuaalinen tila saavutetaan suorilla DOM-manipulaatioilla. Tämä abstraktio on merkittävästi yksinkertaistanut käyttöliittymien kehitystä, tehden sovelluksista ennustettavampia, helpommin ymmärrettäviä ja erittäin suorituskykyisiä.
Todellisen maailman web-sovellukset ovat kuitenkin harvoin täysin deklaratiivisia. On olemassa erityisiä, mutta yleisiä, skenaarioita, joissa suora vuorovaikutus taustalla olevan DOM (Document Object Model) -elementin tai luokkakomponentin instanssin kanssa ei ole vain kätevää, vaan ehdottoman välttämätöntä. Näitä "hätäuloskäyntejä" Reactin deklaratiivisesta virrasta kutsutaan refeiksi. Niistä monista mekanismeista, joita React tarjoaa näiden viittausten luomiseen ja hallintaan, React.createRef() on perustavanlaatuinen API, joka on erityisen tärkeä luokkakomponenttien kanssa työskenteleville kehittäjille.
Tämän kattavan oppaan tavoitteena on olla lopullinen resurssisi React.createRef():n ymmärtämiseen, toteuttamiseen ja hallitsemiseen. Aloitamme yksityiskohtaisen tutkimusmatkan sen tarkoitukseen, syvennymme sen syntaksiin ja käytännön sovelluksiin, valaisemme sen parhaita käytäntöjä ja erotamme sen muista refien hallintastrategioista. Olitpa sitten kokenut React-kehittäjä, joka haluaa vankentaa ymmärrystään imperatiivisista vuorovaikutuksista, tai uusi tulokas, joka pyrkii ymmärtämään tämän ratkaisevan tärkeän käsitteen, tämä artikkeli antaa sinulle tiedot, joilla voit rakentaa vankempia, suorituskykyisempiä ja globaalisti saavutettavampia React-sovelluksia, jotka käsittelevät sulavasti nykyaikaisten käyttäjäkokemusten monimutkaisia vaatimuksia.
Refien ymmärtäminen Reactissa: Silta deklaratiivisen ja imperatiivisen maailman välillä
Pohjimmiltaan React kannattaa deklaratiivista ohjelmointityyliä. Määrittelet komponenttisi, niiden tilan ja miten ne renderöidään. React ottaa sitten ohjat käsiinsä ja päivittää tehokkaasti selaimen DOM-puuta vastaamaan ilmoittamaasi käyttöliittymää. Tämä abstraktiokerros on valtavan voimakas, suojaten kehittäjiä suoran DOM-manipulaation monimutkaisuuksilta ja suorituskykyansoilta. Siksi React-sovellukset tuntuvat usein niin sulavilta ja reagoivilta.
Yksisuuntainen datavirta ja sen rajoitukset
Reactin arkkitehtoninen vahvuus piilee sen yksisuuntaisessa datavirrassa. Data virtaa ennustettavasti alaspäin vanhempikomponenteista lapsille propsien kautta, ja tilamuutokset komponentin sisällä käynnistävät uudelleenrenderöintejä, jotka etenevät sen alipuun läpi. Tämä malli edistää ennustettavuutta ja tekee virheenjäljityksestä huomattavasti helpompaa, koska tiedät aina, mistä data on peräisin ja miten se vaikuttaa käyttöliittymään. Kaikki vuorovaikutukset eivät kuitenkaan sovi täydellisesti tähän ylhäältä alas -datavirtaan.
Harkitse skenaarioita, kuten:
- Syöttökentän ohjelmallinen kohdistaminen, kun käyttäjä siirtyy lomakkeelle.
play()- taipause()-metodien käynnistäminen<video>-elementissä.- Renderöidyn
<div>-elementin tarkkojen pikselimittojen mittaaminen asettelun dynaamiseksi säätämiseksi. - Monimutkaisen kolmannen osapuolen JavaScript-kirjaston (esim. D3.js:n kaltainen kaaviokirjasto tai kartan visualisointityökalu) integrointi, joka odottaa suoraa pääsyä DOM-säiliöön.
Nämä toiminnot ovat luonnostaan imperatiivisia – ne sisältävät elementin suoran käskemisen tekemään jotain sen sijaan, että vain ilmoitettaisiin sen haluttu tila. Vaikka Reactin deklaratiivinen malli voi usein abstrahoida pois monia imperatiivisia yksityiskohtia, se ei poista niiden tarvetta kokonaan. Juuri tässä refit tulevat kuvaan, tarjoten hallitun hätäuloskäynnin näiden suorien vuorovaikutusten suorittamiseen.
Milloin käyttää rejä: Imperatiivisten ja deklaratiivisten vuorovaikutusten navigointi
Tärkein periaate refien kanssa työskennellessä on käyttää niitä säästeliäästi ja vain ehdottoman välttämättömissä tapauksissa. Jos tehtävä voidaan suorittaa käyttämällä Reactin standardeja deklaratiivisia mekanismeja (tila ja propsit), sen tulisi aina olla ensisijainen lähestymistapasi. Liiallinen refien käyttö voi johtaa koodiin, jota on vaikeampi ymmärtää, ylläpitää ja jäljittää, mikä heikentää juuri niitä etuja, joita React tarjoaa.
Kuitenkin tilanteissa, jotka aidosti vaativat suoraa pääsyä DOM-solmuun tai komponentin instanssiin, refit ovat oikea ja tarkoitettu ratkaisu. Tässä on yksityiskohtaisempi erittely sopivista käyttötapauksista:
- Fokuksen, tekstin valinnan ja median toiston hallinta: Nämä ovat klassisia esimerkkejä, joissa sinun on imperatiivisesti vuorovaikutettava elementtien kanssa. Ajattele hakukentän automaattista kohdistamista sivun latautuessa, kaiken tekstin valitsemista syöttökentässä tai ääni- tai videosoittimen toiston hallintaa. Nämä toiminnot käynnistyvät tyypillisesti käyttäjän tapahtumista tai komponentin elinkaarimetodeista, eivätkä pelkästään muuttamalla propseja tai tilaa.
- Imperatiivisten animaatioiden käynnistäminen: Vaikka monet animaatiot voidaan käsitellä deklaratiivisesti CSS-siirtymillä/animaatioilla tai React-animaatiokirjastoilla, jotkut monimutkaiset, suorituskykyiset animaatiot, erityisesti ne, jotka sisältävät HTML Canvas API:n, WebGL:n tai vaativat hienojakoista hallintaa elementin ominaisuuksista, joita on parasta hallita Reactin renderöintisyklin ulkopuolella, saattavat vaatia rejä.
- Integrointi kolmannen osapuolen DOM-kirjastoihin: Monet vanhat JavaScript-kirjastot (esim. D3.js, Leaflet karttoihin, erilaiset vanhat käyttöliittymätyökalupakit) on suunniteltu manipuloimaan suoraan tiettyjä DOM-elementtejä. Refit tarjoavat välttämättömän sillan, joka antaa Reactin renderöidä säiliöelementin ja antaa sitten kolmannen osapuolen kirjastolle pääsyn kyseiseen säiliöön sen omaa imperatiivista renderöintilogiikkaa varten.
-
Elementin mittojen tai sijainnin mittaaminen: Edistyneiden asettelujen, virtualisoinnin tai mukautettujen vierityskäyttäytymisten toteuttamiseksi tarvitset usein tarkkaa tietoa elementin koosta, sen sijainnista näkymäalueeseen nähden tai sen vierityskorkeudesta. API:t, kuten
getBoundingClientRect(), ovat käytettävissä vain todellisilla DOM-solmuilla, mikä tekee refeistä välttämättömiä tällaisissa laskelmissa.
Toisaalta sinun tulisi välttää refien käyttöä tehtäviin, jotka voidaan saavuttaa deklaratiivisesti. Tämä sisältää:
- Komponentin tyylin muokkaaminen (käytä tilaa ehdolliseen muotoiluun).
- Elementin tekstisisällön muuttaminen (välitä propsina tai päivitä tilaa).
- Monimutkainen komponenttien välinen viestintä (propsit ja takaisinkutsut ovat yleensä parempia).
- Kaikki skenaariot, joissa yrität jäljitellä tilanhallinnan toiminnallisuutta.
Syventyminen React.createRef():iin: Nykyaikainen lähestymistapa luokkakomponenteille
React.createRef() esiteltiin React 16.3:ssa, tarjoten selkeämmän ja puhtaamman tavan hallita rejä verrattuna vanhempiin menetelmiin, kuten merkkijonorefeihin (nyt vanhentunut) ja takaisinkutsurefeihin (edelleen voimassa, mutta usein monisanaisempi). Se on suunniteltu ensisijaiseksi refien luontimekanismiksi luokkakomponenteille, tarjoten oliopohjaisen API:n, joka sopii luontevasti luokkarakenteeseen.
Syntaksi ja peruskäyttö: Kolmivaiheinen prosessi
createRef():n käyttötapa on suoraviivainen ja sisältää kolme keskeistä vaihetta:
-
Luo ref-olio: Luokkakomponentin konstruktorissa alusta ref-instanssi kutsumalla
React.createRef()ja osoittamalla sen palautusarvo instanssin ominaisuuteen (esim.this.myRef). -
Liitä ref: Komponentin
render-metodissa välitä luotu ref-olio React-elementinref-attribuuttiin (joko HTML-elementti tai luokkakomponentti), johon haluat viitata. -
Käytä kohdetta: Kun komponentti on liitetty (mountattu), viitattu DOM-solmu tai komponentin instanssi on saatavilla ref-olion
.current-ominaisuuden kautta (esim.this.myRef.current).
import React from 'react';
class FocusInputOnMount extends React.Component {
constructor(props) {
super(props);
this.inputElementRef = React.createRef(); // Vaihe 1: Luo ref-olio konstruktorissa
console.log('Konstruktori: Refin nykyinen arvo on aluksi:', this.inputElementRef.current); // null
}
componentDidMount() {
if (this.inputElementRef.current) {
this.inputElementRef.current.focus();
console.log('ComponentDidMount: Syöttökenttä kohdistettu. Nykyinen arvo:', this.inputElementRef.current.value);
}
}
handleButtonClick = () => {
if (this.inputElementRef.current) {
alert(`Syöttökentän arvo: ${this.inputElementRef.current.value}`);
}
};
render() {
console.log('Render: Refin nykyinen arvo on:', this.inputElementRef.current); // Edelleen null ensimmäisessä renderöinnissä
return (
<div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
<h3>Automaattisesti kohdistuva syöttökenttä</h3>
<label htmlFor="focusInput">Syötä nimesi:</label><br />
<input
id="focusInput"
type="text"
ref={this.inputElementRef} // Vaihe 2: Liitä ref <input>-elementtiin
placeholder="Nimesi tähän..."
style={{ margin: '10px 0', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }}
/><br />
<button
onClick={this.handleButtonClick}
style={{ padding: '10px 15px', background: '#007bff', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}
>
Näytä syöttökentän arvo
</button>
<p><em>Tämä syöttökenttä kohdistuu automaattisesti, kun komponentti latautuu.</em></p>
</div>
);
}
}
Tässä esimerkissä this.inputElementRef on olio, jota React hallitsee sisäisesti. Kun <input>-elementti renderöidään ja liitetään DOM-puuhun, React osoittaa kyseisen todellisen DOM-solmun this.inputElementRef.current-ominaisuuteen. componentDidMount-elinkaarimetodi on ihanteellinen paikka vuorovaikuttaa refien kanssa, koska se takaa, että komponentti ja sen lapset on renderöity DOM-puuhun ja että .current-ominaisuus on saatavilla ja täytetty.
Refin liittäminen DOM-elementtiin: Suora DOM-pääsy
Kun liität refin standardiin HTML-elementtiin (esim. <div>, <p>, <button>, <img>), ref-olion .current-ominaisuus sisältää todellisen taustalla olevan DOM-elementin. Tämä antaa sinulle rajoittamattoman pääsyn kaikkiin standardin selaimen DOM-API:hin, mikä mahdollistaa sellaisten toimintojen suorittamisen, jotka ovat tyypillisesti Reactin deklaratiivisen hallinnan ulkopuolella. Tämä on erityisen hyödyllistä globaaleissa sovelluksissa, joissa tarkka asettelu, vieritys tai fokuksen hallinta voi olla kriittistä erilaisten käyttäjäympäristöjen ja laitetyyppien välillä.
import React from 'react';
class ScrollToElementExample extends React.Component {
constructor(props) {
super(props);
this.targetDivRef = React.createRef();
this.state = { showScrollButton: false };
}
componentDidMount() {
// Näytä vierityspainike vain, jos sisältöä on riittävästi vierittämiseen
// Tämä tarkistus varmistaa myös, että ref on jo nykyinen.
if (this.targetDivRef.current && window.innerHeight < document.body.scrollHeight) {
this.setState({ showScrollButton: true });
}
}
handleScrollToTarget = () => {
if (this.targetDivRef.current) {
// Käytetään scrollIntoView-metodia sulavaan vieritykseen, laajalti tuettu eri selaimissa maailmanlaajuisesti.
this.targetDivRef.current.scrollIntoView({
behavior: 'smooth', // Animoi vierityksen paremman käyttäjäkokemuksen saavuttamiseksi
block: 'start' // Kohdistaa elementin yläreunan näkymäalueen yläreunaan
});
console.log('Vieritetty kohde-diviin!');
} else {
console.warn('Kohde-div ei ole vielä saatavilla vierittämistä varten.');
}
};
render() {
return (
<div style={{ padding: '15px' }}>
<h2>Vierittäminen tiettyyn elementtiin refin avulla</h2>
<p>Tämä esimerkki osoittaa, kuinka vierittää ohjelmallisesti DOM-elementtiin, joka on näytön ulkopuolella.</p>
{this.state.showScrollButton && (
<button
onClick={this.handleScrollToTarget}
style={{ marginBottom: '20px', padding: '10px 20px', background: '#28a745', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}
>
Vieritä alas kohdealueelle
</button>
)}
<div style={{ height: '1500px', background: '#f8f9fa', padding: '20px', marginBottom: '20px', border: '1px dashed #6c757d' }}>
<p>Täytesisältöä pystysuuntaisen vieritystilan luomiseksi.</p>
<p>Kuvittele pitkiä artikkeleita, monimutkaisia lomakkeita tai yksityiskohtaisia kojelautoja, jotka vaativat käyttäjiä navigoimaan laajassa sisällössä. Ohjelmallinen vieritys varmistaa, että käyttäjät pääsevät nopeasti relevantteihin osioihin ilman manuaalista vaivaa, parantaen saavutettavuutta ja käyttäjäpolkua kaikilla laitteilla ja näyttökoilla.</p>
<p>Tämä tekniikka on erityisen hyödyllinen monisivuisissa lomakkeissa, vaiheittaisissa ohjatuissa toiminnoissa tai syvän navigoinnin sisältävissä yhden sivun sovelluksissa.</p>
</div>
<div
ref={this.targetDivRef} // Liitä ref tähän
style={{
minHeight: '300px',
background: '#e9ecef',
padding: '30px',
border: '2px solid #007bff',
borderRadius: '10px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center'
}}
>
<h3>Olet saavuttanut kohdealueen!</h3>
<p>Tämä on osio, johon vieritimme ohjelmallisesti.</p>
<p>Kyky hallita tarkasti vierityskäyttäytymistä on ratkaisevan tärkeää käyttäjäkokemuksen parantamiseksi, erityisesti mobiililaitteilla, joissa näyttötila on rajallinen ja tarkka navigointi on ensisijaisen tärkeää.</p>
</div>
</div>
);
}
}
Tämä esimerkki havainnollistaa kauniisti, kuinka createRef tarjoaa hallintaa selain-tason vuorovaikutuksiin. Tällaiset ohjelmalliset vieritysominaisuudet ovat kriittisiä monissa sovelluksissa, aina pitkien dokumentaatioiden navigoinnista käyttäjien opastamiseen monimutkaisten työnkulkujen läpi. behavior: 'smooth' -vaihtoehto scrollIntoView-metodissa takaa miellyttävän, animoidun siirtymän, parantaen käyttäjäkokemusta yleisesti.
Refin liittäminen luokkakomponenttiin: Vuorovaikutus instanssien kanssa
Natiivien DOM-elementtien lisäksi voit myös liittää refin luokkakomponentin instanssiin. Kun teet näin, ref-olion .current-ominaisuus sisältää itse todellisen instansoidun luokkakomponentin. Tämä antaa vanhempikomponentille mahdollisuuden kutsua suoraan lapsiluokkakomponentin sisällä määriteltyjä metodeja tai käyttää sen instanssin ominaisuuksia. Vaikka tämä on tehokasta, tätä ominaisuutta tulee käyttää erittäin varovasti, koska se mahdollistaa perinteisen yksisuuntaisen datavirran rikkomisen, mikä voi johtaa vähemmän ennustettavaan sovelluksen käyttäytymiseen.
import React from 'react';
// Lapsiluokkakomponentti
class DialogBox extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false, message: '' };
}
// Metodi, joka on paljastettu vanhemmalle refin kautta
open(message) {
this.setState({ isOpen: true, message });
}
close = () => {
this.setState({ isOpen: false, message: '' });
};
render() {
if (!this.state.isOpen) return null;
return (
<div style={{
position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
padding: '25px 35px', background: 'white', border: '1px solid #ddd', borderRadius: '8px',
boxShadow: '0 5px 15px rgba(0,0,0,0.2)', zIndex: 1000, maxWidth: '400px', width: '90%', textAlign: 'center'
}}>
<h4>Viesti vanhemmalta</h4>
<p>{this.state.message}</p>
<button
onClick={this.close}
style={{ marginTop: '15px', padding: '8px 15px', background: '#dc3545', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}
>
Sulje
</button>
</div>
);
}
}
// Vanhempiluokkakomponentti
class AppWithDialog extends React.Component {
constructor(props) {
super(props);
this.dialogRef = React.createRef();
}
handleOpenDialog = () => {
if (this.dialogRef.current) {
// Käytä lapsikomponentin instanssia ja kutsu sen 'open'-metodia
this.dialogRef.current.open('Hei vanhempikomponentilta! Tämä dialogi avattiin imperatiivisesti.');
}
};
render() {
return (
<div style={{ padding: '20px', textAlign: 'center' }}>
<h2>Vanhempi-lapsi-kommunikaatio refin kautta</h2>
<p>Tämä havainnollistaa, kuinka vanhempikomponentti voi imperatiivisesti hallita lapsiluokkakomponentin metodia.</p>
<button
onClick={this.handleOpenDialog}
style={{ padding: '12px 25px', background: '#007bff', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '1.1em' }}
>
Avaa imperatiivinen dialogi
</button>
<DialogBox ref={this.dialogRef} /> // Liitä ref luokkakomponentin instanssiin
</div>
);
}
}
Tässä AppWithDialog voi suoraan kutsua DialogBox-komponentin open-metodia sen refin kautta. Tämä malli voi olla hyödyllinen käynnistettäessä toimintoja, kuten modaali-ikkunan näyttäminen, lomakkeen nollaaminen tai ulkoisten käyttöliittymäelementtien ohjelmallinen hallinta, jotka on kapseloitu lapsikomponenttiin. On kuitenkin yleensä suositeltavaa suosia prop-pohjaista viestintää useimmissa skenaarioissa, välittämällä dataa ja takaisinkutsuja alaspäin vanhemmalta lapselle selkeän ja ennustettavan datavirran ylläpitämiseksi. Turvaudu refeihin lapsikomponentin metodeille vain, kun kyseiset toiminnot ovat aidosti imperatiivisia eivätkä sovi tyypilliseen prop/tila-virtaan.
Refin liittäminen funktionaaliseen komponenttiin (ratkaiseva ero)
Yleinen harhaluulo ja tärkeä erottelupiste on, että et voi suoraan liittää reffiä käyttämällä createRef():ää funktionaaliseen komponenttiin. Funktionaalisilla komponenteilla ei luonnostaan ole instansseja samalla tavalla kuin luokkakomponenteilla. Jos yrität määrittää refin suoraan funktionaaliseen komponenttiin (esim. <MyFunctionalComponent ref={this.myRef} />), React antaa varoituksen kehitystilassa, koska ei ole komponentin instanssia, johon .current voitaisiin osoittaa.
Jos tavoitteenasi on antaa vanhempikomponentille (joka voi olla luokkakomponentti käyttäen createRef:iä tai funktionaalinen komponentti käyttäen useRef:iä) pääsy funktionaalisen lapsikomponentin sisällä renderöityyn DOM-elementtiin, sinun on käytettävä React.forwardRef:iä. Tämä korkeamman asteen komponentti antaa funktionaalisille komponenteille mahdollisuuden paljastaa ref tiettyyn DOM-solmuun tai imperatiiviseen kahvaan itsessään.
Vaihtoehtoisesti, jos työskentelet funktionaalisen komponentin sisällä ja tarvitset luoda ja hallita reffiä, sopiva mekanismi on useRef-hook, jota käsitellään lyhyesti myöhemmässä vertailuosiossa. On elintärkeää muistaa, että createRef on pohjimmiltaan sidottu luokkakomponentteihin ja niiden instanssipohjaiseen luonteeseen.
DOM-solmun tai komponentin instanssin käyttö: `.current`-ominaisuus selitettynä
Ref-vuorovaikutuksen ydin pyörii React.createRef():n luoman ref-olion .current-ominaisuuden ympärillä. Sen elinkaaren ja sen, mitä se voi sisältää, ymmärtäminen on ensisijaisen tärkeää tehokkaan ref-hallinnan kannalta.
`.current`-ominaisuus: Porttisi imperatiiviseen hallintaan
.current-ominaisuus on muuttuva olio, jota React hallitsee. Se toimii suorana linkkinä viitattuun elementtiin tai komponentin instanssiin. Sen arvo muuttuu komponentin elinkaaren aikana:
-
Alustus: Kun kutsut ensimmäisen kerran
React.createRef():ää konstruktorissa, ref-olio luodaan ja sen.current-ominaisuus alustetaan arvoonnull. Tämä johtuu siitä, että tässä vaiheessa komponentti ei ole vielä renderöitynyt, eikä DOM-elementtiä tai komponentin instanssia ole olemassa, johon ref voisi osoittaa. -
Liittäminen (Mounting): Kun komponentti renderöidään DOM-puuhun ja
ref-attribuutilla varustettu elementti luodaan, React osoittaa todellisen DOM-solmun tai luokkakomponentin instanssin ref-olion.current-ominaisuuteen. Tämä tapahtuu tyypillisesti hetirender-metodin päättymisen jälkeen ja ennencomponentDidMount-metodin kutsumista. SiksicomponentDidMounton turvallisin ja yleisin paikka käyttää ja vuorovaikuttaa.current:n kanssa. -
Poistaminen (Unmounting): Kun komponentti poistetaan DOM-puusta, React palauttaa automaattisesti
.current-ominaisuuden takaisin arvoonnull. Tämä on ratkaisevan tärkeää muistivuotojen estämiseksi ja sen varmistamiseksi, että sovelluksesi ei pidä kiinni viittauksista elementteihin, jotka eivät enää ole olemassa DOM-puussa. -
Päivittäminen: Harvinaisissa tapauksissa, joissa
ref-attribuutti vaihdetaan elementissä päivityksen aikana, vanhan refincurrent-ominaisuus asetetaan arvoonnullennen kuin uuden refincurrent-ominaisuus asetetaan. Tämä käyttäytyminen on harvinaisempaa, mutta tärkeä huomioida monimutkaisissa dynaamisissa ref-määrityksissä.
import React from 'react';
class RefLifecycleLogger extends React.Component {
constructor(props) {
super(props);
this.myDivRef = React.createRef();
console.log('1. Konstruktori: this.myDivRef.current on', this.myDivRef.current); // null
}
componentDidMount() {
console.log('3. componentDidMount: this.myDivRef.current on', this.myDivRef.current); // Todellinen DOM-elementti
if (this.myDivRef.current) {
this.myDivRef.current.style.backgroundColor = '#d4edda'; // Imperatiivinen tyylitys demonstrointia varten
this.myDivRef.current.innerText += ' - Ref on aktiivinen!';
}
}
componentDidUpdate(prevProps, prevState) {
console.log('4. componentDidUpdate: this.myDivRef.current on', this.myDivRef.current); // Todellinen DOM-elementti (päivitysten jälkeen)
}
componentWillUnmount() {
console.log('5. componentWillUnmount: this.myDivRef.current on', this.myDivRef.current); // Todellinen DOM-elementti (juuri ennen nollaamista)
// Tässä vaiheessa voit suorittaa siivoustoimia tarvittaessa
}
render() {
// Ensimmäisessä renderöinnissä this.myDivRef.current on edelleen null, koska DOM-puuta ei ole vielä luotu.
// Seuraavissa renderöinneissä (liittämisen jälkeen) se sisältää elementin.
console.log('2. Render: this.myDivRef.current on', this.myDivRef.current);
return (
<div
ref={this.myDivRef}
style={{ padding: '20px', border: '1px solid #28a745', margin: '20px', minHeight: '80px', display: 'flex', alignItems: 'center' }}
>
<p>Tämä on div, johon on liitetty ref.</p>
</div>
);
}
}
RefLifecycleLogger:n konsolitulosteen tarkkailu antaa selkeän kuvan siitä, milloin this.myDivRef.current tulee saataville. On ratkaisevan tärkeää aina tarkistaa, että this.myDivRef.current ei ole null ennen kuin yrität vuorovaikuttaa sen kanssa, erityisesti metodeissa, jotka saattavat suorittua ennen liittämistä tai poistamisen jälkeen.
Mitä `.current` voi sisältää? Refin sisällön tutkiminen
Arvon tyyppi, jonka current sisältää, riippuu siitä, mihin liität refin:
-
Kun liitetty HTML-elementtiin (esim.
<div>,<input>):.current-ominaisuus sisältää todellisen taustalla olevan DOM-elementin. Tämä on natiivi JavaScript-olio, joka tarjoaa pääsyn koko sen DOM-API-valikoimaan. Esimerkiksi, jos liität refin<input type="text">-elementtiin,.currentonHTMLInputElement-olio, joka antaa sinun kutsua metodeja kuten.focus(), lukea ominaisuuksia kuten.valuetai muokata attribuutteja kuten.placeholder. Tämä on yleisin käyttötapaus refeille.this.inputRef.current.focus();
this.videoRef.current.play();
const { width, height } = this.divRef.current.getBoundingClientRect(); -
Kun liitetty luokkakomponenttiin (esim.
<MyClassComponent />):.current-ominaisuus sisältää kyseisen luokkakomponentin instanssin. Tämä tarkoittaa, että voit suoraan kutsua kyseisen lapsikomponentin sisällä määriteltyjä metodeja (esim.childRef.current.someMethod()) tai jopa käyttää sen tilaa tai propseja (vaikka tilan/propsien suora käyttö lapselta refin kautta on yleensä epäsuositeltavaa propsien ja tilapäivitysten hyväksi). Tämä ominaisuus on tehokas tiettyjen käyttäytymisten käynnistämiseen lapsikomponenteissa, jotka eivät sovi standardiin prop-pohjaiseen vuorovaikutusmalliin.this.childComponentRef.current.resetForm();
// Harvoin, mutta mahdollista: console.log(this.childComponentRef.current.state.someValue); -
Kun liitetty funktionaaliseen komponenttiin (
forwardRef:n kautta): Kuten aiemmin todettiin, rejä ei voi liittää suoraan funktionaalisiin komponentteihin. Kuitenkin, jos funktionaalinen komponentti on käärittyReact.forwardRef:llä,.current-ominaisuus sisältää sen arvon, jonka funktionaalinen komponentti nimenomaisesti paljastaa edelleenlähetetyn refin kautta. Tämä on tyypillisesti DOM-elementti funktionaalisen komponentin sisällä tai olio, joka sisältää imperatiivisia metodeja (käyttäenuseImperativeHandle-hookia yhdessäforwardRef:n kanssa).// Vanhemmassa myForwardedRef.current olisi paljastettu DOM-solmu tai olio
this.myForwardedRef.current.focus();
this.myForwardedRef.current.customResetMethod();
Käytännön käyttötapaukset `createRef`:lle toiminnassa
Ymmärtääksemme todella React.createRef():n hyödyllisyyden, tutkitaan yksityiskohtaisempia, globaalisti relevantteja skenaarioita, joissa se osoittautuu välttämättömäksi, siirtyen yksinkertaisen fokuksen hallinnan ulkopuolelle.
1. Fokuksen, tekstin valinnan tai median toiston hallinta eri kulttuureissa
Nämä ovat erinomaisia esimerkkejä imperatiivisista käyttöliittymävuorovaikutuksista. Kuvittele monivaiheinen lomake, joka on suunniteltu globaalille yleisölle. Kun käyttäjä on täyttänyt yhden osion, saatat haluta siirtää fokuksen automaattisesti seuraavan osion ensimmäiseen syöttökenttään, riippumatta kielestä tai oletustekstin suunnasta (vasemmalta oikealle tai oikealta vasemmalle). Refit tarjoavat tarvittavan hallinnan.
import React from 'react';
class DynamicFocusForm extends React.Component {
constructor(props) {
super(props);
this.firstNameRef = React.createRef();
this.lastNameRef = React.createRef();
this.emailRef = React.createRef();
this.state = { currentStep: 1 };
}
componentDidMount() {
// Kohdista ensimmäiseen syöttökenttään, kun komponentti liitetään
this.firstNameRef.current.focus();
}
handleNextStep = (nextRef) => {
this.setState(prevState => ({ currentStep: prevState.currentStep + 1 }), () => {
// Tilapäivitysten ja komponentin uudelleenrenderöinnin jälkeen kohdista seuraava syöttökenttä
if (nextRef.current) {
nextRef.current.focus();
}
});
};
render() {
const { currentStep } = this.state;
const formSectionStyle = { border: '1px solid #0056b3', padding: '20px', margin: '15px 0', borderRadius: '8px', background: '#e7f0fa' };
const inputStyle = { width: '100%', padding: '10px', margin: '8px 0', border: '1px solid #ccc', borderRadius: '4px' };
const buttonStyle = { padding: '10px 20px', background: '#007bff', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer', marginTop: '10px' };
return (
<div style={{ maxWidth: '600px', margin: '30px auto', padding: '25px', boxShadow: '0 4px 12px rgba(0,0,0,0.1)', borderRadius: '10px', background: 'white' }}>
<h2>Monivaiheinen lomake ref-hallitulla fokuksella</h2>
<p>Nykyinen vaihe: <strong>{currentStep}</strong></p>
{currentStep === 1 && (
<div style={formSectionStyle}>
<h3>Henkilötiedot</h3>
<label htmlFor="firstName">Etunimi:</label>
<input id="firstName" type="text" ref={this.firstNameRef} style={inputStyle} placeholder="esim. Matti" />
<label htmlFor="lastName">Sukunimi:</label>
<input id="lastName" type="text" ref={this.lastNameRef} style={inputStyle} placeholder="esim. Meikäläinen" />
<button onClick={() => this.handleNextStep(this.emailRef)} style={buttonStyle}>Seuraava →</button>
</div>
)}
{currentStep === 2 && (
<div style={formSectionStyle}>
<h3>Yhteystiedot</h3>
<label htmlFor="email">Sähköposti:</label>
<input id="email" type="email" ref={this.emailRef} style={inputStyle} placeholder="esim. matti.meikalainen@example.com" />
<p>... muut yhteystiedot ...</p>
<button onClick={() => alert('Lomake lähetetty!')} style={buttonStyle}>Lähetä</button>
</div>
)}
<p><em>Tämä vuorovaikutus parantaa merkittävästi saavutettavuutta ja käyttäjäkokemusta, erityisesti käyttäjille, jotka käyttävät näppäimistönavigointia tai aputeknologioita maailmanlaajuisesti.</em></p>
</div>
);
}
}
Tämä esimerkki esittelee käytännöllisen monivaiheisen lomakkeen, jossa createRef:iä käytetään fokuksen hallintaan ohjelmallisesti. Tämä takaa sujuvan ja saavutettavan käyttäjäpolun, mikä on kriittinen näkökohta sovelluksille, joita käytetään erilaisissa kielellisissä ja kulttuurisissa yhteyksissä. Vastaavasti mediasoittimille refit antavat sinun rakentaa mukautettuja ohjaimia (toista, tauko, äänenvoimakkuus, kelaus), jotka vuorovaikuttavat suoraan HTML5 <video>- tai <audio>-elementtien natiivien API-rajapintojen kanssa, tarjoten yhtenäisen kokemuksen riippumatta selaimen oletusarvoista.
2. Imperatiivisten animaatioiden ja Canvas-vuorovaikutusten käynnistäminen
Vaikka deklaratiiviset animaatiokirjastot ovat erinomaisia moniin käyttöliittymätehosteisiin, jotkut edistyneet animaatiot, erityisesti ne, jotka hyödyntävät HTML5 Canvas API:a, WebGL:ää tai vaativat hienojakoista hallintaa elementin ominaisuuksista, joita on parasta hallita Reactin renderöintisyklin ulkopuolella, hyötyvät suuresti refeistä. Esimerkiksi reaaliaikaisen datan visualisoinnin tai pelin luominen Canvas-elementille sisältää piirtämisen suoraan pikselipuskuriin, mikä on luonnostaan imperatiivinen prosessi.
import React from 'react';
class CanvasAnimator extends React.Component {
constructor(props) {
super(props);
this.canvasRef = React.createRef();
this.animationFrameId = null;
}
componentDidMount() {
this.startAnimation();
}
componentWillUnmount() {
this.stopAnimation();
}
startAnimation = () => {
const canvas = this.canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext('2d');
let angle = 0;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 50;
const animate = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height); // Tyhjennä kangas
// Piirrä pyörivä neliö
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(angle);
ctx.fillStyle = '#6f42c1';
ctx.fillRect(-radius / 2, -radius / 2, radius, radius);
ctx.restore();
angle += 0.05; // Kasvata kulmaa pyörimistä varten
this.animationFrameId = requestAnimationFrame(animate);
};
this.animationFrameId = requestAnimationFrame(animate);
};
stopAnimation = () => {
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId);
}
};
render() {
return (
<div style={{ textAlign: 'center', margin: '30px auto', border: '1px solid #ced4da', padding: '20px', borderRadius: '8px', background: '#f8f9fa' }}>
<h3>Imperatiivinen Canvas-animaatio createRef:llä</h3>
<p>Tätä canvas-animaatiota ohjataan suoraan selain-API:lla refin kautta.</p>
<canvas ref={this.canvasRef} width="300" height="200" style={{ border: '1px solid #adb5bd', background: 'white' }}>
Selaimesi ei tue HTML5 canvas -tagia.
</canvas>
<p><em>Tällainen suora hallinta on elintärkeää suorituskykyiselle grafiikalle, peleille tai erikoistuneille datavisualisoinneille, joita käytetään eri teollisuudenaloilla maailmanlaajuisesti.</em></p>
</div>
);
}
}
Tämä komponentti tarjoaa canvas-elementin ja käyttää reffiä saadakseen suoran pääsyn sen 2D-renderöintikontekstiin. Animaatiosilmukka, joka toimii `requestAnimationFrame`:n avulla, piirtää ja päivittää imperatiivisesti pyörivää neliötä. Tämä malli on perustavanlaatuinen interaktiivisten kojelautojen, online-suunnittelutyökalujen tai jopa rentojen pelien rakentamisessa, jotka vaativat tarkkaa, ruutu ruudulta -renderöintiä riippumatta käyttäjän maantieteellisestä sijainnista tai laitteen ominaisuuksista.
3. Integrointi kolmannen osapuolen DOM-kirjastoihin: Saumaton silta
Yksi pakottavimmista syistä käyttää rejä on Reactin integrointi ulkoisiin JavaScript-kirjastoihin, jotka manipuloivat suoraan DOM-puuta. Monet tehokkaat kirjastot, erityisesti vanhemmat tai ne, jotka keskittyvät tiettyihin renderöintitehtäviin (kuten kaavioihin, karttoihin tai rikastetun tekstin editointiin), toimivat ottamalla DOM-elementin kohteeksi ja hallitsemalla sitten sen sisältöä itse. React, deklaratiivisessa tilassaan, olisi muutoin ristiriidassa näiden kirjastojen kanssa yrittämällä hallita samaa DOM-alipuuta. Refit estävät tämän konfliktin tarjoamalla nimetyn 'säiliön' ulkoiselle kirjastolle.
import React from 'react';
import * as d3 from 'd3'; // Olettaen, että D3.js on asennettu ja tuotu
class D3BarChart extends React.Component {
constructor(props) {
super(props);
this.chartContainerRef = React.createRef();
}
// Kun komponentti liitetään, piirrä kaavio
componentDidMount() {
this.drawChart();
}
// Kun komponentti päivittyy (esim. props.data muuttuu), päivitä kaavio
componentDidUpdate(prevProps) {
if (prevProps.data !== this.props.data) {
this.drawChart();
}
}
// Kun komponentti poistetaan, siivoa D3-elementit muistivuotojen estämiseksi
componentWillUnmount() {
d3.select(this.chartContainerRef.current).selectAll('*').remove();
}
drawChart = () => {
const data = this.props.data || [40, 80, 20, 100, 60, 90]; // Oletusdata
const node = this.chartContainerRef.current;
if (!node) return; // Varmista, että ref on saatavilla
// Tyhjennä kaikki aiemmat D3:n piirtämät kaavioelementit
d3.select(node).selectAll('*').remove();
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = 460 - margin.left - margin.right;
const height = 300 - margin.top - margin.bottom;
const svg = d3.select(node)
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// Määritä asteikot
const x = d3.scaleBand()
.range([0, width])
.padding(0.1);
const y = d3.scaleLinear()
.range([height, 0]);
x.domain(data.map((d, i) => i)); // Käytä indeksiä domainina yksinkertaisuuden vuoksi
y.domain([0, d3.max(data)]);
// Lisää palkit
svg.selectAll('.bar')
.data(data)
.enter().append('rect')
.attr('class', 'bar')
.attr('x', (d, i) => x(i))
.attr('width', x.bandwidth())
.attr('y', d => y(d))
.attr('height', d => height - y(d))
.attr('fill', '#17a2b8');
// Lisää X-akseli
svg.append('g')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom(x));
// Lisää Y-akseli
svg.append('g')
.call(d3.axisLeft(y));
};
render() {
return (
<div style={{ textAlign: 'center', margin: '30px auto', border: '1px solid #00a0b2', padding: '20px', borderRadius: '8px', background: '#e0f7fa' }}>
<h3>D3.js-kaavion integrointi React createRef:llä</h3>
<p>Tämä datavisualisointi on renderöity D3.js:llä React-hallitun säiliön sisällä.</p>
<div ref={this.chartContainerRef} /> // D3.js renderöi tähän diviin
<p><em>Tällaisten erikoistuneiden kirjastojen integrointi on ratkaisevan tärkeää dataintensiivisille sovelluksille, tarjoten tehokkaita analyyttisiä työkaluja käyttäjille eri teollisuudenaloilla ja alueilla.</em></p>
</div>
);
}
}
Tämä laaja esimerkki esittelee D3.js-pylväskaavion integroinnin React-luokkakomponentin sisään. chartContainerRef antaa D3.js:lle tarvittavan DOM-solmun sen renderöintiä varten. React käsittelee säiliö-<div>:n elinkaaren, kun taas D3.js hallitsee sen sisäistä sisältöä. `componentDidUpdate`- ja `componentWillUnmount`-metodit ovat elintärkeitä kaavion päivittämiseksi datan muuttuessa ja tarvittavan siivouksen suorittamiseksi, estäen muistivuodot ja varmistaen reagoivan kokemuksen. Tämä malli on yleisesti sovellettavissa, antaen kehittäjille mahdollisuuden hyödyntää sekä Reactin komponenttimallin parhaita puolia että erikoistuneita, suorituskykyisiä visualisointikirjastoja globaaleihin kojelautoihin ja analytiikka-alustoihin.
4. Elementin mittojen tai sijainnin mittaaminen dynaamisia asetteluja varten
Erittäin dynaamisia tai responsiivisia asetteluja varten, tai ominaisuuksien kuten virtualisoitujen listojen toteuttamiseksi, jotka renderöivät vain näkyviä kohteita, elementtien tarkkojen mittojen ja sijainnin tunteminen on kriittistä. Refit antavat sinulle pääsyn getBoundingClientRect()-metodiin, joka antaa tämän tärkeän tiedon suoraan DOM-puusta.
import React from 'react';
class ElementDimensionLogger extends React.Component {
constructor(props) {
super(props);
this.measurableDivRef = React.createRef();
this.state = {
width: 0,
height: 0,
top: 0,
left: 0,
message: 'Napsauta painiketta mitataksesi!'
};
}
componentDidMount() {
// Alkuperäinen mittaus on usein hyödyllinen, mutta sen voi myös käynnistää käyttäjän toiminto
this.measureElement();
// Dynaamisia asetteluja varten voit kuunnella ikkunan koonmuutostapahtumia
window.addEventListener('resize', this.measureElement);
}
componentWillUnmount() {
window.removeEventListener('resize', this.measureElement);
}
measureElement = () => {
if (this.measurableDivRef.current) {
const rect = this.measurableDivRef.current.getBoundingClientRect();
this.setState({
width: Math.round(rect.width),
height: Math.round(rect.height),
top: Math.round(rect.top),
left: Math.round(rect.left),
message: 'Mitat päivitetty.'
});
} else {
this.setState({ message: 'Elementtiä ei ole vielä renderöity.' });
}
};
render() {
const { width, height, top, left, message } = this.state;
const boxStyle = {
width: '70%',
minHeight: '150px',
border: '3px solid #ffc107',
margin: '25px auto',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
background: '#fff3cd',
borderRadius: '8px',
textAlign: 'center'
};
return (
<div style={{ maxWidth: '700px', margin: '30px auto', padding: '25px', boxShadow: '0 4px 12px rgba(0,0,0,0.08)', borderRadius: '10px', background: 'white' }}>
<h3>Elementin mittojen mittaaminen createRef:llä</h3>
<p>Tämä esimerkki hakee ja näyttää dynaamisesti kohde-elementin koon ja sijainnin.</p>
<div ref={this.measurableDivRef} style={boxStyle}>
<p><strong>Minä olen mitattava elementti.</strong></p>
<p>Muuta selaimesi ikkunan kokoa nähdäksesi mittojen muuttuvan päivityksen/manuaalisen käynnistyksen yhteydessä.</p>
</div>
<button
onClick={this.measureElement}
style={{ padding: '10px 20px', background: '#6c757d', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer', marginBottom: '15px' }}
>
Mittaa nyt
</button>
<div style={{ background: '#f0f0f0', padding: '15px', borderRadius: '6px' }}>
<p><strong>Live-mitat:</strong></p>
<ul style={{ listStyleType: 'none', padding: 0, textAlign: 'left', margin: '0 auto', maxWidth: '300px' }}>
<li>Leveys: <b>{width}px</b></li>
<li>Korkeus: <b>{height}px</b></li>
<li>Sijainti ylhäältä (näkymäalue): <b>{top}px</b></li>
<li>Sijainti vasemmalta (näkymäalue): <b>{left}px</b></li>
</ul>
<p><em>Tarkka elementin mittaus on kriittistä responsiivisille suunnitteluille ja suorituskyvyn optimoimiseksi erilaisilla laitteilla maailmanlaajuisesti.</em></p>
</div>
</div>
);
}
}
Tämä komponentti käyttää createRef:iä saadakseen getBoundingClientRect()-arvon div-elementistä, tarjoten sen reaaliaikaiset mitat ja sijainnin. Tämä tieto on korvaamatonta toteutettaessa monimutkaisia asettelun säätöjä, määritettäessä näkyvyyttä virtualisoidussa vierityslistassa tai jopa varmistettaessa, että elementit ovat tietyllä näkymäalueella. Globaalille yleisölle, jossa näyttöjen koot, resoluutiot ja selainympäristöt vaihtelevat suuresti, tarkka asettelun hallinta todellisten DOM-mittausten perusteella on avaintekijä yhtenäisen ja laadukkaan käyttäjäkokemuksen tarjoamisessa.
Parhaat käytännöt ja varoitukset `createRef`:n käytössä
Vaikka createRef tarjoaa tehokkaan imperatiivisen hallinnan, sen väärinkäyttö voi johtaa vaikeasti hallittavaan ja jäljitettävään koodiin. Parhaiden käytäntöjen noudattaminen on välttämätöntä sen voiman vastuullisessa hyödyntämisessä.
1. Priorisoi deklaratiiviset lähestymistavat: Kultainen sääntö
Muista aina, että refit ovat "hätäuloskäynti", eivät ensisijainen vuorovaikutustapa Reactissa. Ennen kuin tartut refiin, kysy itseltäsi: Voidaanko tämä saavuttaa tilalla ja propseilla? Jos vastaus on kyllä, se on lähes aina parempi, enemmän "React-idiomaattinen" lähestymistapa. Esimerkiksi, jos haluat muuttaa syöttökentän arvoa, käytä kontrolloituja komponentteja tilan kanssa, älä reffiä asettaaksesi suoraan inputRef.current.value.
2. Refit ovat imperatiivisia vuorovaikutuksia varten, eivät tilanhallintaa
Refit soveltuvat parhaiten tehtäviin, jotka sisältävät suoria, imperatiivisia toimintoja DOM-elementeille tai komponenttien instansseille. Ne ovat komentoja: "kohdista tämä syöttökenttä", "toista tämä video", "vieritä tähän osioon". Niitä ei ole tarkoitettu muuttamaan komponentin deklaratiivista käyttöliittymää tilan perusteella. Elementin tyylin tai sisällön suora manipulointi refin kautta, kun sitä voitaisiin hallita propseilla tai tilalla, voi johtaa siihen, että Reactin virtuaalinen DOM ei ole enää synkronissa todellisen DOM-puun kanssa, aiheuttaen ennustamatonta käyttäytymistä ja renderöintiongelmia.
3. Refit ja funktionaaliset komponentit: Omaksu `useRef` ja `forwardRef`
Nykyaikaisessa React-kehityksessä funktionaalisten komponenttien sisällä React.createRef() ei ole työkalu, jota käytät. Sen sijaan turvaudut useRef-hookiin. useRef-hook tarjoaa muuttuvan ref-olion, joka on samanlainen kuin createRef, jonka .current-ominaisuutta voidaan käyttää samoihin imperatiivisiin vuorovaikutuksiin. Se säilyttää arvonsa komponentin uudelleenrenderöintien yli aiheuttamatta itse uudelleenrenderöintiä, mikä tekee siitä täydellisen viittauksen pitämiseen DOM-solmuun tai mihin tahansa muuttuvaan arvoon, jonka on säilyttävä renderöintien välillä.
import React, { useRef, useEffect } from 'react';
function FunctionalComponentWithRef() {
const myInputRef = useRef(null); // Alusta null-arvolla
useEffect(() => {
// Tämä suoritetaan komponentin liittämisen jälkeen
if (myInputRef.current) {
myInputRef.current.focus();
console.log('Funktionaalisen komponentin syöttökenttä kohdistettu!');
}
}, []); // Tyhjä riippuvuuslista varmistaa, että se suoritetaan vain kerran liittämisen yhteydessä
const handleLogValue = () => {
if (myInputRef.current) {
alert(`Syöttökentän arvo: ${myInputRef.current.value}`);
}
};
return (
<div style={{ margin: '20px', padding: '20px', border: '1px solid #009688', borderRadius: '8px', background: '#e0f2f1' }}>
<h3>useRef:n käyttö funktionaalisessa komponentissa</h3>
<label htmlFor="funcInput">Kirjoita jotain:</label><br />
<input id="funcInput" type="text" ref={myInputRef} placeholder="Minut kohdistetaan automaattisesti!" style={{ padding: '8px', margin: '10px 0', borderRadius: '4px', border: '1px solid #ccc' }} /><br />
<button onClick={handleLogValue} style={{ padding: '10px 15px', background: '#009688', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}>
Kirjaa syöttökentän arvo
</button>
<p><em>Uusissa projekteissa `useRef` on idiomaattinen valinta refeille funktionaalisissa komponenteissa.</em></p>
</div>
);
}
Jos tarvitset vanhempikomponentin saamaan refin funktionaalisen lapsikomponentin sisällä olevaan DOM-elementtiin, ratkaisusi on React.forwardRef. Se on korkeamman asteen komponentti, jonka avulla voit "välittää edelleen" refin vanhemmalta yhdelle sen lasten DOM-elementeistä, säilyttäen funktionaalisen komponentin kapseloinnin ja mahdollistaen silti imperatiivisen pääsyn tarvittaessa.
import React, { useRef, useEffect } from 'react';
// Funktionaalinen komponentti, joka välittää refin eteenpäin natiiville input-elementilleen
const ForwardedInput = React.forwardRef((props, ref) => (
<input type="text" ref={ref} className="forwarded-input" placeholder={props.placeholder} style={{ padding: '10px', margin: '8px 0', border: '1px solid #ccc', borderRadius: '4px', width: '100%' }} />
));
class ParentComponentUsingForwardRef extends React.Component {
constructor(props) {
super(props);
this.parentInputRef = React.createRef();
}
componentDidMount() {
if (this.parentInputRef.current) {
this.parentInputRef.current.focus();
console.log('Funktionaalisen komponentin sisällä oleva syöttökenttä kohdistettu vanhemmalta (luokkakomponentilta) edelleenlähetetyn refin kautta!');
}
}
render() {
return (
<div style={{ margin: '20px', padding: '20px', border: '1px solid #6f42c1', borderRadius: '8px', background: '#f5eef9' }}>
<h3>Refin edelleenlähetyksen esimerkki createRef:llä (Vanhempi luokkakomponentti)</h3>
<label>Syötä tiedot:</label>
<ForwardedInput ref={this.parentInputRef} placeholder="Tämä syöttökenttä on funktionaalisen komponentin sisällä" />
<p><em>Tämä malli on ratkaisevan tärkeä uudelleenkäytettävien komponenttikirjastojen luomisessa, joiden on paljastettava suora DOM-pääsy.</em></p>
</div>
);
}
}
Tämä osoittaa, kuinka createRef:iä käyttävä luokkakomponentti voi tehokkaasti vuorovaikuttaa funktionaalisen komponentin sisällä olevan DOM-elementin kanssa hyödyntämällä forwardRef:iä. Tämä tekee funktionaalisista komponenteista yhtä kykeneviä osallistumaan imperatiivisiin vuorovaikutuksiin tarvittaessa, varmistaen, että modernit React-koodikannat voivat edelleen hyötyä refeistä.
4. Milloin ei pidä käyttää rejä: Reactin eheyden säilyttäminen
- Lapsikomponentin tilan hallintaan: Älä koskaan käytä reffiä suoraan lapsikomponentin tilan lukemiseen tai päivittämiseen. Tämä ohittaa Reactin tilanhallinnan, tehden sovelluksestasi ennustamattoman. Sen sijaan välitä tila alas propseina ja käytä takaisinkutsuja, jotta lapset voivat pyytää tilamuutoksia vanhemmilta.
- Propsien korvikkeena: Vaikka voit kutsua metodeja lapsiluokkakomponentilla refin kautta, harkitse, saavuttaisiko tapahtumankäsittelijän välittäminen propsina lapselle saman tavoitteen "React-idiomaattisemmalla" tavalla. Propsit edistävät selkeää datavirtaa ja tekevät komponenttien vuorovaikutuksista läpinäkyviä.
-
Yksinkertaisiin DOM-manipulaatioihin, jotka React voi hoitaa: Jos haluat muuttaa elementin tekstiä, tyyliä tai lisätä/poistaa luokan tilan perusteella, tee se deklaratiivisesti. Esimerkiksi, jos haluat vaihtaa luokan
active, sovella sitä ehdollisesti JSX:ssä:<div className={isActive ? 'active' : ''}>, sen sijaan että tekisitdivRef.current.classList.add('active').
5. Suorituskykynäkökohdat ja globaali ulottuvuus
Vaikka createRef itsessään on suorituskykyinen, current:n avulla suoritetuilla operaatioilla voi olla merkittäviä suorituskykyvaikutuksia. Käyttäjille, joilla on heikompitehoisia laitteita tai hitaampia verkkoyhteyksiä (yleistä monissa osissa maailmaa), tehottomat DOM-manipulaatiot voivat johtaa nykimiseen, reagoimattomiin käyttöliittymiin ja huonoon käyttäjäkokemukseen. Kun käytät rejä tehtäviin, kuten animaatioihin, monimutkaisiin asettelulaskelmiin tai raskaiden kolmannen osapuolen kirjastojen integrointiin:
-
Debounce/Throttle-tapahtumat: Jos käytät rejä mittojen mittaamiseen
window.resize- taiscroll-tapahtumissa, varmista, että nämä käsittelijät on debouncoitu tai throttlattu liiallisten funktiokutsujen ja DOM-lukujen estämiseksi. -
Ryhmittele DOM-luvut/kirjoitukset: Vältä DOM-lukuoperaatioiden (esim.
getBoundingClientRect()) ja DOM-kirjoitusoperaatioiden (esim. tyylien asettaminen) vuorottelua. Tämä voi aiheuttaa layout thrashingia. Työkalut, kutenfastdom, voivat auttaa hallitsemaan tätä tehokkaasti. -
Viivästytä ei-kriittisiä operaatioita: Käytä
requestAnimationFrame-funktiota animaatioihin jasetTimeout(..., 0)tairequestIdleCallbackvähemmän kriittisiin DOM-manipulaatioihin varmistaaksesi, että ne eivät estä pääsäiettä ja vaikuta reagoivuuteen. - Valitse viisaasti: Joskus kolmannen osapuolen kirjaston suorituskyky voi olla pullonkaula. Arvioi vaihtoehtoja tai harkitse tällaisten komponenttien laiskaa lataamista (lazy-loading) käyttäjille, joilla on hitaammat yhteydet, varmistaen, että peruskokemus säilyy suorituskykyisenä maailmanlaajuisesti.
`createRef` vs. Takaisinkutsurefit vs. `useRef`: Yksityiskohtainen vertailu
React on tarjonnut erilaisia tapoja käsitellä rejä evoluutionsa aikana. Kunkin vivahteiden ymmärtäminen on avain sopivimman menetelmän valitsemiseksi omaan kontekstiisi.
1. `React.createRef()` (Luokkakomponentit - Moderni)
-
Mekanismi: Luo ref-olion (
{ current: null }) komponentin instanssin konstruktorissa. React osoittaa DOM-elementin tai komponentin instanssin.current-ominaisuuteen liittämisen jälkeen. - Ensisijainen käyttö: Yksinomaan luokkakomponenteissa. Se alustetaan kerran per komponentin instanssi.
-
Refin täyttäminen:
.currentasetetaan elementtiin/instanssiin komponentin liittämisen jälkeen ja palautetaan arvoonnullpoistamisen yhteydessä. - Paras käytettäväksi: Kaikkiin standardeihin ref-vaatimuksiin luokkakomponenteissa, joissa sinun on viitattava DOM-elementtiin tai lapsiluokkakomponentin instanssiin.
- Edut: Selkeä, suoraviivainen oliopohjainen syntaksi. Ei huolta siitä, että inline-funktion uudelleenluominen aiheuttaisi ylimääräisiä kutsuja (kuten voi tapahtua takaisinkutsurefien kanssa).
- Haitat: Ei käytettävissä funktionaalisten komponenttien kanssa. Jos sitä ei alusteta konstruktorissa (esim. render-metodissa), uusi ref-olio saatetaan luoda jokaisella renderöinnillä, mikä voi johtaa mahdollisiin suorituskykyongelmiin tai virheellisiin ref-arvoihin. Vaatii muistamista osoittaa instanssin ominaisuuteen.
2. Takaisinkutsurefit (Luokka- ja funktionaaliset komponentit - Joustava/Vanha)
-
Mekanismi: Välität funktion suoraan
ref-propsiin. React kutsuu tätä funktiota liitetyllä DOM-elementillä tai komponentin instanssilla, ja myöhemminnull:lla, kun se poistetaan. -
Ensisijainen käyttö: Voidaan käyttää sekä luokka- että funktionaalisissa komponenteissa. Luokkakomponenteissa takaisinkutsu on yleensä sidottu
this:iin tai määritelty nuolifunktiona luokan ominaisuutena. Funktionaalisissa komponenteissa se määritellään usein inline-tyylisesti tai muistutetaan. -
Refin täyttäminen: React kutsuu takaisinkutsufunktiota suoraan. Olet vastuussa viittauksen tallentamisesta (esim.
this.myInput = element;). -
Paras käytettäväksi: Skenaarioihin, jotka vaativat hienojakoisempaa hallintaa siitä, milloin refit asetetaan ja poistetaan, tai edistyneisiin malleihin, kuten dynaamisiin ref-listoihin. Se oli ensisijainen tapa hallita rejä ennen
createRef:iä jauseRef:iä. - Edut: Tarjoaa maksimaalisen joustavuuden. Antaa sinulle välittömän pääsyn refiin, kun se on saatavilla (takaisinkutsufunktion sisällä). Voidaan käyttää refien tallentamiseen taulukkoon tai mappiin dynaamisia elementtikokoelmia varten.
-
Haitat: Jos takaisinkutsu määritellään inline-tyylisesti
render-metodin sisällä (esim.ref={el => this.myRef = el}), sitä kutsutaan kahdesti päivitysten aikana (kerrannull:lla, sitten elementillä), mikä voi aiheuttaa suorituskykyongelmia tai odottamattomia sivuvaikutuksia, jos sitä ei käsitellä huolellisesti (esim. tekemällä takaisinkutsusta luokkametodin tai käyttämälläuseCallback:ia funktionaalisissa komponenteissa).
class CallbackRefDetailedExample extends React.Component {
constructor(props) {
super(props);
this.inputElement = null;
}
// React kutsuu tätä metodia asettaakseen refin
setInputElementRef = element => {
if (element) {
console.log('Ref-elementti on:', element);
}
this.inputElement = element; // Tallenna todellinen DOM-elementti
};
componentDidMount() {
if (this.inputElement) {
this.inputElement.focus();
}
}
render() {
return (
<div>
<label>Takaisinkutsurefin syöttökenttä:</label>
<input type="text" ref={this.setInputElementRef} />
</div>
);
}
}
3. `useRef` Hook (Funktionaaliset komponentit - Moderni)
-
Mekanismi: React Hook, joka palauttaa muuttuvan ref-olion (
{ current: initialValue }). Palautettu olio säilyy koko funktionaalisen komponentin eliniän ajan. - Ensisijainen käyttö: Yksinomaan funktionaalisissa komponenteissa.
-
Refin täyttäminen: Samanlainen kuin
createRef, React osoittaa DOM-elementin tai komponentin instanssin (jos edelleenlähetetty).current-ominaisuuteen liittämisen jälkeen ja asettaa sen arvoonnullpoistamisen yhteydessä..current-arvoa voidaan myös päivittää manuaalisesti. - Paras käytettäväksi: Kaikkiin ref-hallintaan funktionaalisissa komponenteissa. Hyödyllinen myös minkä tahansa muuttuvan arvon säilyttämiseen, jonka on säilyttävä renderöintien välillä ilman uudelleenrenderöinnin käynnistämistä (esim. ajastin-ID:t, aiemmat arvot).
- Edut: Yksinkertainen, idiomaattinen Hookeille. Ref-olio säilyy renderöintien välillä, välttäen uudelleenluontiongelmia. Voi tallentaa minkä tahansa muuttuvan arvon, ei vain DOM-solmuja.
-
Haitat: Toimii vain funktionaalisten komponenttien sisällä. Vaatii nimenomaisen
useEffect:n elinkaareen liittyviin ref-vuorovaikutuksiin (kuten kohdistaminen liittämisen yhteydessä).
Yhteenvetona:
-
Jos kirjoitat luokkakomponenttia ja tarvitset refin,
React.createRef()on suositeltu ja selkein valinta. -
Jos kirjoitat funktionaalista komponenttia ja tarvitset refin,
useRef-hook on moderni, idiomaattinen ratkaisu. - Takaisinkutsurefit ovat edelleen päteviä, mutta yleensä monisanaisempia ja alttiimpia hienovaraisille ongelmille, jos niitä ei toteuteta huolellisesti. Ne ovat hyödyllisiä edistyneissä skenaarioissa tai työskenneltäessä vanhempien koodikantojen tai kontekstien kanssa, joissa hookit eivät ole saatavilla.
-
Refien välittämiseen komponenttien läpi (erityisesti funktionaalisten),
React.forwardRef()on välttämätön, ja sitä käytetään usein yhdessäcreateRef:n taiuseRef:n kanssa vanhempikomponentissa.
Globaalit näkökohdat ja edistynyt saavutettavuus refien avulla
Vaikka rejä käsitellään usein teknisessä tyhjiössä, niiden käytöllä globaalisti suunnatussa sovelluskontekstissa on tärkeitä seurauksia, erityisesti suorituskyvyn ja saavutettavuuden osalta erilaisille käyttäjille.
1. Suorituskyvyn optimointi erilaisille laitteille ja verkoille
createRef:n itsensä vaikutus paketin kokoon on minimaalinen, koska se on pieni osa Reactin ydintä. Kuitenkin operaatioilla, joita suoritat current-ominaisuudella, voi olla merkittäviä suorituskykyvaikutuksia. Käyttäjille, joilla on heikompitehoisia laitteita tai hitaampia verkkoyhteyksiä (yleistä monissa osissa maailmaa), tehottomat DOM-manipulaatiot voivat johtaa nykimiseen, reagoimattomiin käyttöliittymiin ja huonoon käyttäjäkokemukseen. Kun käytät rejä tehtäviin, kuten animaatioihin, monimutkaisiin asettelulaskelmiin tai raskaiden kolmannen osapuolen kirjastojen integrointiin:
-
Debounce/Throttle-tapahtumat: Jos käytät rejä mittojen mittaamiseen
window.resize- taiscroll-tapahtumissa, varmista, että nämä käsittelijät on debouncoitu tai throttlattu liiallisten funktiokutsujen ja DOM-lukujen estämiseksi. -
Ryhmittele DOM-luvut/kirjoitukset: Vältä DOM-lukuoperaatioiden (esim.
getBoundingClientRect()) ja DOM-kirjoitusoperaatioiden (esim. tyylien asettaminen) vuorottelua. Tämä voi aiheuttaa layout thrashingia. Työkalut, kutenfastdom, voivat auttaa hallitsemaan tätä tehokkaasti. -
Viivästytä ei-kriittisiä operaatioita: Käytä
requestAnimationFrame-funktiota animaatioihin jasetTimeout(..., 0)tairequestIdleCallbackvähemmän kriittisiin DOM-manipulaatioihin varmistaaksesi, että ne eivät estä pääsäiettä ja vaikuta reagoivuuteen. - Valitse viisaasti: Joskus kolmannen osapuolen kirjaston suorituskyky voi olla pullonkaula. Arvioi vaihtoehtoja tai harkitse tällaisten komponenttien laiskaa lataamista (lazy-loading) käyttäjille, joilla on hitaammat yhteydet, varmistaen, että peruskokemus säilyy suorituskykyisenä maailmanlaajuisesti.
2. Saavutettavuuden parantaminen (ARIA-attribuutit ja näppäimistönavigointi)
Refit ovat avainasemassa erittäin saavutettavien verkkosovellusten rakentamisessa, erityisesti luotaessa mukautettuja käyttöliittymäkomponentteja, joilla ei ole natiiveja selainvastaavia, tai ohitettaessa oletuskäyttäytymisiä. Globaalille yleisölle Web Content Accessibility Guidelines (WCAG) -ohjeiden noudattaminen ei ole vain hyvää käytäntöä, vaan usein lakisääteinen vaatimus. Refit mahdollistavat:
- Ohjelmallinen fokuksen hallinta: Kuten syöttökenttien kanssa nähtiin, refit antavat sinun asettaa fokuksen, mikä on ratkaisevan tärkeää näppäimistön käyttäjille ja ruudunlukijanavigoinnille. Tämä sisältää fokuksen hallinnan modaali-ikkunoissa, pudotusvalikoissa tai interaktiivisissa widgeteissä.
-
Dynaamiset ARIA-attribuutit: Voit käyttää rejä dynaamisesti lisäämään tai päivittämään ARIA (Accessible Rich Internet Applications) -attribuutteja (esim.
aria-expanded,aria-controls,aria-live) DOM-elementeissä. Tämä tarjoaa semanttista tietoa aputeknologioille, jota ei välttämättä voi päätellä pelkästään visuaalisesta käyttöliittymästä.class CollapsibleSection extends React.Component {
constructor(props) {
super(props);
this.buttonRef = React.createRef();
this.state = { isExpanded: false };
}
toggleExpanded = () => {
this.setState(prevState => ({ isExpanded: !prevState.isExpanded }), () => {
if (this.buttonRef.current) {
// Päivitä ARIA-attribuutti dynaamisesti tilan perusteella
this.buttonRef.current.setAttribute('aria-expanded', this.state.isExpanded);
}
});
};
componentDidMount() {
if (this.buttonRef.current) {
this.buttonRef.current.setAttribute('aria-controls', `section-${this.props.id}`);
this.buttonRef.current.setAttribute('aria-expanded', this.state.isExpanded);
}
}
render() {
const { id, title, children } = this.props;
const { isExpanded } = this.state;
return (
<div style={{ margin: '20px auto', maxWidth: '600px', border: '1px solid #0056b3', borderRadius: '8px', background: '#e7f0fa', overflow: 'hidden' }}>
<h4>
<button
ref={this.buttonRef} // Ref painikkeeseen ARIA-attribuutteja varten
onClick={this.toggleExpanded}
style={{ background: 'none', border: 'none', padding: '15px 20px', width: '100%', textAlign: 'left', cursor: 'pointer', fontSize: '1.2em', color: '#0056b3', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}
id={`section-header-${id}`}
>
{title} <span>▼</span>
</button>
</h4>
{isExpanded && (
<div id={`section-${id}`} role="region" aria-labelledby={`section-header-${id}`} style={{ padding: '0 20px 20px', borderTop: '1px solid #a7d9f7' }}>
{children}
</div>
)}
</div>
);
}
} - Näppäimistövuorovaikutuksen hallinta: Mukautetuille pudotusvalikoille, liukusäätimille tai muille interaktiivisille elementeille saatat joutua toteuttamaan erityisiä näppäimistötapahtumien käsittelijöitä (esim. nuolinäppäimet navigointiin listan sisällä). Refit tarjoavat pääsyn kohde-DOM-elementtiin, johon nämä tapahtumakuuntelijat voidaan liittää ja hallita.
Soveltamalla rejä harkitusti kehittäjät voivat varmistaa, että heidän sovelluksensa ovat käytettäviä ja osallistavia vammaisille ihmisille maailmanlaajuisesti, laajentaen huomattavasti niiden globaalia ulottuvuutta ja vaikutusta.
3. Kansainvälistäminen (I18n) ja lokalisoidut vuorovaikutukset
Kansainvälistämisen (i18n) parissa työskenneltäessä refit voivat olla hienovarainen mutta tärkeä rooli. Esimerkiksi kielissä, jotka käyttävät oikealta vasemmalle (RTL) -kirjoitusjärjestelmää (kuten arabia, heprea tai persia), luonnollinen sarkainjärjestys ja vierityssuunta voivat poiketa vasemmalta oikealle (LTR) -kielistä. Jos hallitset fokusta tai vieritystä ohjelmallisesti refien avulla, on ratkaisevan tärkeää varmistaa, että logiikkasi kunnioittaa dokumentin tai elementin tekstin suuntaa (dir-attribuutti).
- RTL-tietoinen fokuksen hallinta: Vaikka selaimet yleensä käsittelevät oletussarkainjärjestyksen oikein RTL:lle, jos toteutat mukautettuja fokusloukkuja tai peräkkäistä fokusointia, testaa ref-pohjainen logiikkasi perusteellisesti RTL-ympäristöissä varmistaaksesi yhtenäisen ja intuitiivisen kokemuksen.
-
Asettelun mittaus RTL:ssä: Kun käytät
getBoundingClientRect():ää refin kautta, ole tietoinen siitä, ettäleft- jaright-ominaisuudet ovat suhteessa näkymäalueeseen. Asettelulaskelmissa, jotka riippuvat visuaalisesta alusta/lopusta, harkitsedocument.dir:iä tai elementin laskettua tyyliä säätääksesi logiikkaasi RTL-asetteluille. - Kolmannen osapuolen kirjastojen integrointi: Varmista, että kaikki refien kautta integroidut kolmannen osapuolen kirjastot (esim. kaaviokirjastot) ovat itse i18n-tietoisia ja käsittelevät RTL-asettelut oikein, jos sovelluksesi tukee niitä. Vastuu tämän varmistamisesta lankeaa usein kehittäjälle, joka integroi kirjaston React-komponenttiin.
Johtopäätös: Imperatiivisen hallinnan mestarointi `createRef`:llä globaaleihin sovelluksiin
React.createRef() on enemmän kuin vain "hätäuloskäynti" Reactissa; se on elintärkeä työkalu, joka kuromaa umpeen kuilun Reactin tehokkaan deklaratiivisen paradigman ja selaimen DOM-vuorovaikutusten imperatiivisten todellisuuksien välillä. Vaikka sen roolin uudemmissa funktionaalisissa komponenteissa on suurelta osin ottanut haltuunsa useRef-hook, createRef pysyy standardina ja idiomaattisimpana tapana hallita rejä luokkakomponenteissa, jotka muodostavat edelleen merkittävän osan monista yrityssovelluksista maailmanlaajuisesti.
Ymmärtämällä perusteellisesti sen luomisen, liittämisen ja .current-ominaisuuden kriittisen roolin, kehittäjät voivat luottavaisesti tarttua haasteisiin, kuten ohjelmalliseen fokuksen hallintaan, suoraan median hallintaan, saumattomaan integrointiin erilaisten kolmannen osapuolen kirjastojen kanssa (D3.js-kaavioista mukautettuihin rikastetun tekstin editoreihin) ja tarkkaan elementin mittojen mittaamiseen. Nämä kyvyt eivät ole vain teknisiä saavutuksia; ne ovat perustavanlaatuisia sovellusten rakentamisessa, jotka ovat suorituskykyisiä, saavutettavia ja käyttäjäystävällisiä laajalle kirjolle globaaleja käyttäjiä, laitteita ja kulttuurikonteksteja.
Muista käyttää tätä valtaa harkitusti. Suosi aina ensin Reactin deklaratiivista tila- ja prop-järjestelmää. Kun imperatiivista hallintaa todella tarvitaan, createRef (luokkakomponenteille) tai useRef (funktionaalisille komponenteille) tarjoaa vankan ja hyvin määritellyn mekanismin sen saavuttamiseksi. Refien hallitseminen antaa sinulle voiman käsitellä modernin web-kehityksen reunatapauksia ja monimutkaisuuksia, varmistaen, että React-sovelluksesi voivat tarjota poikkeuksellisia käyttäjäkokemuksia kaikkialla maailmassa, säilyttäen samalla Reactin elegantin komponenttipohjaisen arkkitehtuurin ydinhyödyt.
Lisäoppiminen ja tutkiminen
- Reactin virallinen dokumentaatio refeistä: Ajantasaisimmat tiedot suoraan lähteestä, katso <em>https://react.dev/learn/manipulating-the-dom-with-refs</em>
- Reactin `useRef`-hookin ymmärtäminen: Sukeltaaksesi syvemmälle funktionaalisen komponentin vastaavaan, tutustu <em>https://react.dev/reference/react/useRef</em>
- Refin edelleenlähetys `forwardRef`:llä: Opi välittämään rejä tehokkaasti komponenttien läpi: <em>https://react.dev/reference/react/forwardRef</em>
- Verkkosisällön saavutettavuusohjeet (WCAG): Välttämätöntä globaalille web-kehitykselle: <em>https://www.w3.org/WAI/WCAG22/quickref/</em>
- Reactin suorituskyvyn optimointi: Parhaat käytännöt suorituskykyisille sovelluksille: <em>https://react.dev/learn/optimizing-performance</em>