Rozpoczynamy serię szybkich, na początku łatwych, lekcji o React + TypeScript. Jedno i drugie próbowaliśmy osobno, pora to wszystko połączyć. Do dzieła.
Ok, po pierwsze użyjmy create-react-app tak jak zawsze, ale dopiszmy flagę –template na typescript:
npx create-react-app my-app --template typescript
Możemy też przez vite utworzyć. Ja to vite poznałem przez Laravela, ale można tego spokojnie używać i też projekty tworzy jakie chcemy.
Ok, posprzątajmy App.tsx:
import React from 'react';
import './App.css';
function App() {
return (
<div className="App">
</div>
);
}
export default App;
Jak widzimy, pliki .js to teraz .ts, zaś .jsx to .tsx. Tego się trzymajmy. Ok, zaimportujmy useRef i po TSowemu użyjmy:
import { useRef } from 'react';
function App() {
let ref = useRef<number>(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You clicked ' + ref.current + ' times!');
}
Czyli podaliśmy, że typ refa to ma być number. Zobaczmy, co nam edytor podpowiada przy ref oraz przy ref.current:
function App() {
let ref = useRef<number>(0);
//let ref: React.MutableRefObject<number>
function handleClick() {
ref.current = ref.current + 1;
//(property) React.MutableRefObject<number>.current: number
alert('You clicked ' + ref.current + ' times!');
}
Sam App zwraca nam JSX.Element:
function App(): JSX.Element {
let ref = useRef<number>(0);
function handleClick() {
ref.current = ref.current + 1;
alert('You clicked ' + ref.current + ' times!');
}
return (
<div className="App">
<button onClick={handleClick}>Click me!</button>
</div>
);
}
export default App;
Już tutaj sobie dopisaliśmy ten kawałek JSXa. Mamy też typ React.ReactNode, tutaj się nie przyda, ale miejmy go na oku.
Ok, zrobimy sobie inputa:
return (
<div className="App">
<button onClick={handleClick}>Click me!</button>
<input type="text" ref={ipt} />
</div>
);
Teraz ref:
import { useRef, useEffect } from 'react';
function App(): JSX.Element {
let ref = useRef<number>(0);
let ipt = useRef<HTMLInputElement>(null);
Musimy podać odpowiedni interfejs elementu HTML. Natomiast null przechodzi jako wartość początkowa. Musimy tylko porządny guard dać w useEffect:
useEffect(() => {
if (ipt.current) {
ipt.current.focus();
}
}, []);
Takie coś jednak nie przejdzie:
function App(): JSX.Element {
let ref = useRef<number>(null);
let ipt = useRef<HTMLInputElement>(null);
Ok, postarajmy się poprawić to:
function App(): JSX.Element {
let ref = useRef<number|null>(null);
let ipt = useRef<HTMLInputElement>(null);
function handleClick() {
ref.current = ref.current + 1; //dalej error
alert('You clicked ' + ref.current + ' times!');
}
Error to ref.current is possibly null. To wyeliminujmy tę możliwość:
function handleClick() {
if(!ref.current){
ref.current = 1;
}
ref.current = ref.current + 1;
alert('You clicked ' + ref.current + ' times!');
}
Niby ok, ale teraz mamy na początek 2 times. Ok, zróbmy tak:
function handleClick() {
if(ref.current){
ref.current = ref.current + 1;
} else {
ref.current = 1;
}
alert('You clicked ' + ref.current + ' times!');
}
Działa. Więcej TS oraz React już niedługo!