Irbisa · Шпаргалка
Хуки подробно
Правила хуков, кастомные хуки, useReducer, useContext, useMemo и useCallback, useId, useSyncExternalStore, useTransition, use
Какие есть правила хуков и зачем они нужны React?
Что такое кастомный хук и когда его стоит выносить?
function useDebouncedValue<T>(value: T, delayMs: number): T { const [debounced, setDebounced] = useState(value); useEffect(() => { const id = setTimeout(() => setDebounced(value), delayMs); return () => clearTimeout(id);…Какую проблему решает
useContextи как предоставить и прочитать контекст?type Theme = 'light' | 'dark';const ThemeContext = createContext<Theme>('light'); function App() { const [theme, setTheme] = useState<Theme>('dark'); return (…Когда стоит использовать
useReducerвместоuseState?type State = { items: string[]; draft: string };type Action = | { type: 'typed'; text: string } | { type: 'added' } | { type: 'removed'; index: number };…Чем отличаются
useMemoиReact.memo?// React.memo: wraps a component, skips its render when props are equalconst Row = memo(function Row({ item }: { item: Item }) { return <li>{item.name}</li>;}); function ProductList({ items, query }: { items: Item[]; query: string }) {…Как React понимает, какой вызов
useStateвозвращает какое состояние, если у хуков нет имён и ключей?Чем отличаются
useMemoиuseCallbackи когда их стоит использовать?const Chart = memo(function Chart({ points, onSelect }: ChartProps) { /* expensive SVG rendering */}); function Dashboard({ rows, filter }: { rows: Row[]; filter: string }) { const [selected, setSelected] = useState<string | null>(null);…Почему при изменении значения контекста ререндерятся все его потребители и как ограничить эти ререндеры?
Найдите баг: профиль работает для гостей, но после входа страница падает с ошибкой "Rendered more hooks than during the previous render".
function Profile() { const user = useContext(UserContext); if (!user) return <SignInPrompt />; const [orders, setOrders] = useState<Order[]>([]); useEffect(() => { fetchOrders(user.id).then(setOrders); }, [user.id]); return <OrderList user={user} orders={orders} />;}Что выведется в консоль, если пользователь трижды нажмёт «+1», а потом «Log»?
function Counter() { const [count, setCount] = useState(0); const log = useCallback(() => { console.log(count); }, []); return ( <> <button onClick={() => setCount(count + 1)}>+1</button> <button onClick={log}>Log</button> </> );}Как объединить
useReducerи контекст для управления состоянием фичи и где этот паттерн перестаёт масштабироваться?const CartContext = createContext<CartState | null>(null);const CartDispatchContext = createContext<Dispatch<CartAction> | null>(null); export function CartProvider({ children }: { children: React.ReactNode }) { const [cart, dispatch] = useReducer(cartReducer, { lines: [] }); return (…Для чего нужен
useIdи почему не генерировать id черезMath.random()или счётчик в модуле?function EmailField() { const id = useId(); return ( <div> <label htmlFor={`${id}-email`}>Email</label> <input id={`${id}-email`} type="email" aria-describedby={`${id}-hint`} />…Что делают
useTransitionиuseDeferredValueи когда выбирать каждый?function Search({ items }: { items: Item[] }) { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); // lags behind while rendering const isStale = query !== deferredQuery; return (…Что такое API
useв React 19 и чем он отличается от других хуков?// PostPage.tsx, a Server Component: starts the request, does not await itexport default function PostPage({ postId }: { postId: string }) { const commentsPromise = fetchComments(postId); return ( <Suspense fallback={<Spinner />}> <Comments commentsPromise={commentsPromise} />…Как написать хук
useDebounceдля поля поиска?// debounced value: the usual hook for a search inputfunction useDebouncedValue<T>(value: T, delayMs: number): T { const [debounced, setDebounced] = useState(value); useEffect(() => { const timer = setTimeout(() => setDebounced(value), delayMs); return () => clearTimeout(timer); // the next keystroke cancels the pending update…Как написать хук
useLocalStorageи как синхронизировать его между вкладками и сделать безопасным при серверном рендеринге?function subscribe(callback: () => void) { window.addEventListener('storage', callback); // writes from other tabs window.addEventListener('local-storage', callback); // writes from this tab return () => { window.removeEventListener('storage', callback); window.removeEventListener('local-storage', callback);…Что такое
useSyncExternalStoreи почему внешние сторы должны использовать его, а неuseStateплюсuseEffect?function subscribe(callback: () => void) { window.addEventListener('online', callback); window.addEventListener('offline', callback); return () => { window.removeEventListener('online', callback); window.removeEventListener('offline', callback);…Найдите баг: бейдж корзины подвешивает вкладку с ошибкой "The result of getSnapshot should be cached to avoid an infinite loop".
function useCartSummary() { return useSyncExternalStore(cartStore.subscribe, () => ({ count: cartStore.getState().items.length, total: cartStore.getState().total, }));} function CartBadge() { const { count, total } = useCartSummary(); return <span>{count} items, ${total}</span>;}Как спроектировать API переиспользуемого кастомного хука, чтобы им было удобно пользоваться и он не вызывал лишних ререндеров?
interface UseDisclosureOptions { defaultOpen?: boolean; onOpenChange?: (open: boolean) => void;} export function useDisclosure({ defaultOpen = false, onOpenChange }: UseDisclosureOptions = {}) {…