مجموعه تعاریف پکیج @types/react شامل مشخصات تمام هوکهای داخلی React است. در اکثر مواقع، تایپاسکریپت بر اساس کدهایی که مینویسید، نوع داده را به صورت خودکار حدس میزند (Inferred Types)؛ بنابراین نیازی به درگیر شدن با جزئیات تعیین نوع ندارید. با این حال، در برخی سناریوها باید نوع داده را صراحتاً اعلام کنید.
useStateاین هوک به طور پیشفرض نوع داده خود را از روی مقدار اولیه (Initial State) حدس میزند:
// تشخیص خودکار نوع داده به عنوان "boolean"
const [enabled, setEnabled] = useState(false);
اگر میخواهید نوع داده را صراحتاً مشخص کنید، میتوانید از یک آرگومان ژنریک (<Type>) استفاده کنید:
const [enabled, setEnabled] = useState<boolean>(false);
مشخص کردن صریح تایپ زمانی کاربرد دارد که وضعیت شما قرار باشد یکی از چند مقدار متنی خاص (Union Type) یا ساختارهای پیچیده را بپذیرد:
// تعیین وضعیتهای مجاز برای یک فرآیند
type Status = "idle" | "loading" | "success" | "error";
const [status, setStatus] = useState<Status>("idle");
همچنین برای مدیریت اصولی وضعیتها، پیشنهاد میشود حالتهای مختلف داده را به صورت اشیاء ساختاریافته (Discriminated Unions) مدلسازی کنید:
type RequestState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: any }
| { status: 'error'; error: Error };
const [requestState, setRequestState] = useState<RequestState>({ status: 'idle' });
useReducerهوک useReducer برای مدیریت وضعیتهای پیچیدهتر به کار میرود و شامل یک تابع ریreducer و یک وضعیت اولیه است. بهترین روش برای استفاده از تایپاسکریپت در این هوک، تعیین نوع روی ساختار وضعیت اولیه و اکشنها است:
import { useReducer } from 'react';
// ۱. تعریف ساختار وضعیت
interface State {
count: number;
}
// ۲. تعریف اکشنهای مجاز ورودی
type CounterAction =
| { type: "reset" }
| { type: "setCount"; value: State["count"] };
const initialState: State = { count: 0 };
// ۳. تعریف تابع ردیوسر همراه با تایپ ورودیها و خروجی
function stateReducer(state: State, action: CounterAction): State {
switch (action.type) {
case "reset":
return initialState;
case "setCount":
return { ...state, count: action.value };
default:
throw new Error("Unknown action");
}
}
export default function App() {
const [state, dispatch] = useReducer(stateReducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "setCount", value: state.count + 5 })}>Add 5</button>
<button onClick={() => dispatch({ type: "reset" })}>Reset</button>
</div>
);
}
useContextاین هوک دادهها را بدون نیاز به پاس دادن پروپها به سطوح پایین دایرکتوری میفرستد. نوع داده کانتکست معمولاً از مقداری که به تابع createContext میدهید حدس زده میشود:
type Theme = "light" | "dark" | "system";
const ThemeContext = createContext<Theme>("system");
nullدر مواردی که کانتکست مقدار پیشفرض منطقی ندارد، استفاده از null رایج است. برای اینکه سیستم دچار خطا نشود، باید کانتکست را به صورت ContextShape | null تعریف کنید.
برای اینکه مصرفکنندگان کانتکست مجبور نباشند در همه جا شرط بررسی null را بنویسند، بهترین راهکار این است که یک هوک اختصاصی بسازید تا وجود کانتکست را در زمان اجرا بررسی کند:
import { createContext, useContext, useState } from 'react';
type ComplexObject = { kind: string };
// تعریف کانتکست که میتواند null هم باشد
const Context = createContext<ComplexObject | null>(null);
// حذف خودکار تداخل null با بررسی در هوک اختصاصی
const useGetComplexObject = () => {
const object = useContext(Context);
if (!object) {
throw new Error("useGetComplexObject must be used within a Provider");
}
return object; // نوع داده بازگشتی کاملاً ComplexObject است و null نیست
};
useMemo و useCallbackنکته بسیار مهم (کامپایلر جدید راکت): کامپایلر جدید React (نسخه React Compiler) مقادیر و توابع را به صورت کاملاً خودکار مموایز (Memoize) میکند. این کار نیاز به استفاده دستی از هوکهای
useMemoوuseCallbackرا به شدت کاهش میدهد.
useMemoنوع داده خروجی بر اساس مقدار بازگشتی تابعی که به آن پاس دادهاید، به طور خودکار استخراج میشود:
// نوع داده visibleTodos دقیقاً همان نوع داده خروجی تابع filterTodos خواهد بود
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
useCallbackدر حالت سختگیرانه تایپاسکریپت (Strict Mode)، باید نوع داده پارامترهای ورودی کالبک را مشخص کنید. شما میتوانید از ساختارهای مدیریت رویداد پیشفرض راکت (*EventHandler) برای تمیزتر شدن کد استفاده کنید:
import { useState, useCallback } from 'react';
export default function Form() {
const [value, setValue] = useState("Change me");
// تعیین نوع دقیق هندلر با استفاده از ساختارهای ژنریک راکت
const handleChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>((event) => {
setValue(event.currentTarget.value);
}, [setValue]);
return <input value={value} onChange={handleChange} />;
}
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://react.dev/learn