Zbieramy to kupy wiedzę z Reacta oraz TypeScripta, łącząc to wszystko. Małymi kroczkami poznajemy React + TypeScript. Zaczynajmy!
Zaczynamy tam, gdzie skończyliśmy. Zaimportujmy useState:
import { useRef, useEffect, useState } from 'react';
Ok, zróbmy stan:
function App(): JSX.Element {
let ipt = useRef<HTMLInputElement>(null);
let [name, setName] = useState<string>("");
Swoją drogą, jeżeli stan ma być tylko jednego typu, to można olać podawanie go jako generyczny argument. TS domyśli się, że chodzi o typ string. Szczerze, myślałem, że takie coś na przykład nie przejdzie:
<p>Your name is {name.trim() === "" ? "unknown": name}</p>
Przechodzi bez problemu, jeżeli initial type to będzie string i innych typów nie będziemy tam mieszać. Co nie zmienia faktu, że lepiej jest wszystko określać, tak powstaje lepszy kod. Nie zawsze, ale bardzo często powinniśmy być konkretni, od tego mamy TSa.
Ok, to nasz JSX (TSX w zasadzie) powinien wyglądać tak:
return (
<div className="App">
<input type="text" ref={ipt} onChange={onChangeIpt} />
<p>Your name is {name.trim() === "" ? "unknown": name}</p>
</div>
);
Teraz zrobimy sobie funkcję onChangeIpt:
function onChangeIpt(e){ // Parameter 'e' implicitly has an 'any' type.
setName(e.target.value);
}
Już mamy problem. Ok, to jaki jest typ tego eventu? Napiszmy tak:
function onChangeIpt(e: React.ChangeEvent){
setName(e.target.value); //Property 'value' does not exist on type 'EventTarget & Element'
}
W dobrym kierunku idziemy, ale to jeszcze nie to. Oszczędzę czytelnikowi kombinowania:
function App(): JSX.Element {
let ipt = useRef<HTMLInputElement>(null);
let [name, setName] = useState<string>("");
// ? ???
useEffect(() => {
if (ipt.current) {
ipt.current.focus();
}
}, []);
function onChangeIpt(e: React.ChangeEvent<HTMLInputElement>){
setName(e.target.value); //ok
}
return (
<div className="App">
<input type="text" ref={ipt} onChange={onChangeIpt} />
<p>Your name is {name.trim() === "" ? "unknown": name}</p>
</div>
);
}
export default App;
Ok, fajnie. To teraz pora się zastanowić, jakiego typu są name i setName. Tutaj edytor nam podpowie, ipt też sobie sprawdźmy:
function App(): JSX.Element {
let ipt = useRef<HTMLInputElement>(null);
//let ipt: React.RefObject<HTMLInputElement>
let [name, setName] = useState<string>("");
//let name: string
//let setName: React.Dispatch<React.SetStateAction<string>>
Ktoś może zapytać a po co mi wiedzieć, jakiego typu jest setName. No, a jak będziesz to przekazywał np. z góry na dół? A na dole komponent ma propsy i musi wiedzieć, jaki typ odbiera.
Takie uroki typowania. Dlatego zaczynamy powoli, bo inaczej to można się totalnie w tym pogubić i dostać gorączki jakiejś.
Więcej TSowego Reacta niedługo!