TypeScript bilan React — props, hooks, events, children tiplari
React da TypeScript eng ko'p ishlatilishi — props, hooks va event handlerlar uchun. Bu darsda amalda kerak bo'lgan barcha asosiy pattern lar.
Props tipizatsiyasi
// interface yoki type — ikkalasi ishlaydi, interface afzalroq
interface ButtonProps {
matn: string;
variant?: "primary" | "secondary" | "danger";
boldi: boolean;
onClick: () => void;
}
function Button({ matn, variant = "primary", boldi, onClick }: ButtonProps) {
return (
<button
disabled={boldi}
className={`btn btn-${variant}`}
onClick={onClick}
>
{matn}
</button>
);
}
children
import { ReactNode } from "react";
interface CardProps {
sarlavha: string;
children: ReactNode; // har qanday React element
}
function Card({ sarlavha, children }: CardProps) {
return (
<div className="card">
<h2>{sarlavha}</h2>
{children}
</div>
);
}
ReactNode — matn, element, massiv, null — hammasi.
useState tipizatsiyasi
import { useState } from "react";
// Qiymatdan tur aniqlanadi
const [son, setSon] = useState(0); // number
const [matn, setMatn] = useState(""); // string
const [faol, setFaol] = useState(false); // boolean
// Aniq ko'rsatish — null bo'lishi mumkin
const [user, setUser] = useState<User | null>(null);
// Ob'ekt
const [forma, setForma] = useState<{ ism: string; email: string }>({
ism: "", email: ""
});
useRef tipizatsiyasi
import { useRef } from "react";
// DOM element uchun
const inputRef = useRef<HTMLInputElement>(null);
const divRef = useRef<HTMLDivElement>(null);
// O'zgaruvchan qiymat uchun (mutable)
const timerRef = useRef<NodeJS.Timeout | null>(null);
// Ishlatish
<input ref={inputRef} />
inputRef.current?.focus(); // optional chaining — null bo'lishi mumkin
Event handler tipizatsiyasi
import { ChangeEvent, FormEvent, MouseEvent } from "react";
function Forma() {
const [qiymat, setQiymat] = useState("");
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setQiymat(e.target.value);
};
const onSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// ...
};
const onClick = (e: MouseEvent<HTMLButtonElement>) => {
console.log(e.currentTarget.textContent);
};
return (
<form onSubmit={onSubmit}>
<input onChange={onChange} value={qiymat} />
<button onClick={onClick}>Yuborish</button>
</form>
);
}
Generic komponent
interface RoYxatProps<T> {
elementlar: T[];
kalit: (el: T) => string | number;
render: (el: T) => ReactNode;
}
function RoYxat<T>({ elementlar, kalit, render }: RoYxatProps<T>) {
return (
<ul>
{elementlar.map(el => (
<li key={kalit(el)}>{render(el)}</li>
))}
</ul>
);
}
// Ishlatish
<RoYxat
elementlar={users}
kalit={u => u.id}
render={u => <span>{u.ism}</span>}
/>
FC vs funksiya
import { FC, ReactNode } from "react";
// FC — React.FunctionComponent, children bilan (eski usul)
const Button: FC<ButtonProps> = ({ matn }) => <button>{matn}</button>;
// Zamonaviy — oddiy funksiya (afzalroq)
function Button({ matn }: ButtonProps) {
return <button>{matn}</button>;
}
FC dan voz kechish sababi — FC avtomatik children qo'shardi (TypeScript 18+ da o'zgartildi).
Xulosa
// Props
interface Props { matn: string; onClick: () => void; }
function Comp({ matn, onClick }: Props) { ... }
// children
import { ReactNode } from "react";
interface Props { children: ReactNode; }
// useState
useState<User | null>(null)
// useRef
useRef<HTMLInputElement>(null)
// Event
(e: ChangeEvent<HTMLInputElement>) => e.target.value
(e: FormEvent<HTMLFormElement>) => e.preventDefault()
(e: MouseEvent<HTMLButtonElement>) => { ... }
Keyingi dars
61-dars: TypeScript bilan Node.js va Express — tiplar, middleware