forwardRef
rajapinnan avulla komponentti voi tarjota DOM noodin pääkomponenetille ref:llä.
const SomeComponent = forwardRef(render)
Viite
forwardRef(render)
Kutsu forwardRef()
-funktiota, jotta komponenttisi voi vastaanottaa ref:n ja välittää sen lapsikomponentille:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
// ...
});
Parametrit
render
: Komponenttisi renderöintifunktio. React kutsuu tätä funktiota komponentin pääkomponentilta saamilla propseilla jaref
:lla. JSX, jonka palautat, on komponenttisi ulostulo.
Palautukset
forwardRef
palauttaa React-komponentin, jonka voit renderöidä JSX:llä. Toisin kuin React-komponentit, jotka on määritelty tavallisina funktioina, forwardRef
:n palauttama komponentti voi myös vastaanottaa ref
propin.
Huomiot
- Strict Modessa, React kutsuu renderöintifunktiotasi kahdesti auttaakseen sinua löytämään tahattomia epäpuhtauksia. Tämä on vain kehitystilassa tapahtuva käyttäytyminen, eikä vaikuta tuotantoon. Jos renderöintifunktiosi on puhdas (kuten sen pitäisi olla), tämä ei vaikuta komponenttisi logiikkaan. Toinen kutsuista jätetään huomiotta.
render
funktio
forwardRef
hyväksyy renderöintifunktion argumenttina. React kutsuu tätä funktiota props
ja ref
-argumenteilla:
const MyInput = forwardRef(function MyInput(props, ref) {
return (
<label>
{props.label}
<input ref={ref} />
</label>
);
});
Parametrit
-
props
: Propsit, jotka pääkomponentti on välittänyt. -
ref
:ref
attribuutti, jonka pääkomponentti on välittänyt.ref
voi olla joko objekti tai funktio. Jos pääkomponentti ei ole välittänyt ref:iä, se onnull
. Sinun tulisi joko välittää saamasiref
toiselle komponentille tai välittää seuseImperativeHandle
:lle.
Palautukset
forwardRef
palauttaa React komponentin, jonka voit renderöidä JSX:llä. Toisin kuin React komponentit, jotka on määritelty tavallisina funktioina, forwardRef
:n palauttama komponentti voi myös vastaanottaa ref
propin.
Käyttö
DOM noodin välittäminen pääkomponentille
Oletuksena jokaisen komponentin DOM noodit ovat yksityisiä. Joskus on kuitenkin hyödyllistä välittää DOM noodi pääkomponentille, esimerkiksi mahdollistaaksesi siihen kohdentamisen. Ottaaksesi tämän käyttöön, kääri komponenttisi forwardRef()
-funktioon:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} />
</label>
);
});
Saat ref -argumentin toisena argumenttina propsien jälkeen. Välitä se DOM noodiin, jonka haluat julkaista:
import { forwardRef } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const { label, ...otherProps } = props;
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
);
});
Tämän avulla pääkomponentti Form
voi käyttää MyInput
komponentin julkaisemaa <input>
DOM noodia:
function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form>
<MyInput label="Enter your name:" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
Form
komponentti välittää ref:n MyInput
:lle. MyInput
komponentti välittää sen ref:n <input>
selaimen tagille. Tämän seurauksena Form
komponentti voi käyttää <input>
DOM noodia ja kutsua focus()
siihen.
Pidä mielessä, että ref:n julkaiseminen komponenttisi sisällä olevaan DOM noodin tekee sen vaikeammaksi muuttaa komponenttisi sisäistä rakennetta myöhemmin. Yleensä julkaiset DOM noodin ref:n uudelleen käytettävistä matalan tason komponenteista, kuten painikkeista tai tekstisyötteistä, mutta et tee sitä sovellustason komponenteille, kuten avatarille tai kommentille.
Esimerkki 1 / 2: Syöttökenttään kohdistaminen
Painiketta painaminen kohdistaa syöttökenttään. Form
komponentti määrittelee ref:n ja välittää sen MyInput
komponentille. MyInput
komponentti välittää sen ref:n selaimen <input>
tagille. Tämän avulla Form
komponentti voi kohdistaa <input>
:in.
import { useRef } from 'react'; import MyInput from './MyInput.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); } return ( <form> <MyInput label="Enter your name:" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
Refin välittäminen useiden komponenttien läpi
Sen sijaan, että välittäisit ref
:n DOM noodille, voit välittää sen omalle komponentillesi kuten MyInput
:
const FormField = forwardRef(function FormField(props, ref) {
// ...
return (
<>
<MyInput ref={ref} />
...
</>
);
});
Jos tämä MyInput
komponentti välittää ref:n <input>
:lle, ref FormField
:lle antaa sinulle tuon <input>
:in:
function Form() {
const ref = useRef(null);
function handleClick() {
ref.current.focus();
}
return (
<form>
<FormField label="Enter your name:" ref={ref} isRequired={true} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
);
}
Form
komponentti määrittää refin ja välittää sen FormField
:lle. FormField
komponentti välittää tuon ref:n MyInput
:lle, joka välittää sen selaimen <input>
DOM noodille. Tämän avulla Form
komponentti voi käsitellä tuota DOM noodia.
import { useRef } from 'react'; import FormField from './FormField.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); } return ( <form> <FormField label="Enter your name:" ref={ref} isRequired={true} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
Imperatiivisen käsittelijän julkaiseminen DOM noden sijaan
Sen sijaan, että julkistaisit koko DOM noodin, voit julkistaa räätälöidyn olion, jota kutsutaan imperatiiviseksi käsittelijäksi, jolla on suppeampi joukko metodeja. Tämän toteuttamiseksi, sinun täytyy määrittää erillinen ref, joka pitää sisällään DOM noodin:
const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);
// ...
return <input {...props} ref={inputRef} />;
});
Välitä vastaanottamasi ref
useImperativeHandle
:lle ja määritä arvo, jonka haluat julkistaa ref
:lle:
import { forwardRef, useRef, useImperativeHandle } from 'react';
const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null);
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
};
}, []);
return <input {...props} ref={inputRef} />;
});
Jos jokin komponentti saa refin MyInput
:lle, saa se vain { focus, scrollIntoView }
olion koko DOM noodin sijaan. Tämän avulla voit rajoittaa DOM noodista julkistettavan informaation minimiin.
import { useRef } from 'react'; import MyInput from './MyInput.js'; export default function Form() { const ref = useRef(null); function handleClick() { ref.current.focus(); // Tämä ei toimi, koska DOM noodi ei ole julkistettu: // ref.current.style.opacity = 0.5; } return ( <form> <MyInput placeholder="Enter your name" ref={ref} /> <button type="button" onClick={handleClick}> Edit </button> </form> ); }
Lue lisää imperatiivisista käsittelijöistä.
Vianmääritys
Komponenttini on kääritty forwardRef
:iin, mutta ref
siihen on aina null
Usein tämä tarkoittaa, että unohdit käyttää ref
:iä, jonka sait.
Esimerkiksi, tämä komponentti ei tee mitään sen ref
:llä:
const MyInput = forwardRef(function MyInput({ label }, ref) {
return (
<label>
{label}
<input />
</label>
);
});
Korjataksesi tämän, välitä ref
DOM noodille tai toiselle komponentille, joka voi vastaanottaa ref:n:
const MyInput = forwardRef(function MyInput({ label }, ref) {
return (
<label>
{label}
<input ref={ref} />
</label>
);
});
ref
MyInput
:lle voi olla myös null
, jos osa logiikasta on ehdollista:
const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
return (
<label>
{label}
{showInput && <input ref={ref} />}
</label>
);
});
Jos showInput
on false
, ref:iä ei välitetä millekään nodille, ja ref MyInput
:lle pysyy tyhjänä. Tämä on erityisen helppo jättää huomaamatta, jos ehto on piilotettu toisen komponentin sisälle, kuten Panel
tässä esimerkissä:
const MyInput = forwardRef(function MyInput({ label, showInput }, ref) {
return (
<label>
{label}
<Panel isExpanded={showInput}>
<input ref={ref} />
</Panel>
</label>
);
});