Welcome Back, React Hooks Made Simple: The Complete Guide, Part-2
In [Part 1] https://dev.to/abrar_galib_5c0cf41ad3a3e/react-hooks-made-simple-the-complete-guide-part-1-2jln we covered the core Hooks (useState, useEffect, useContext), the additional Hooks (useRef, useMemo, useCallback, useReducer) and the advanced ones (useLayoutEffect, useImperativeHandle, useId). If you haven’t read it yet, start there, because everything in this part builds on it. In Part 2: Two Hooks that keep your app smooth when an update is heavy A few more advanced Hooks for outside data and library authors The new Hooks that came with React 19 and later The Hooks that belong to Next.js Custom Hooks, common mistakes, and a cheatsheet you can keep open while you code Everything below works on React 19. A few things need a newer minor version, and I point them out as we go: useEffectEvent needs React 19.2, and ViewTransition, Fragment Refs and use(browser()) need React 19.3, which is the current stable release. Table of Contents Performance Hooks useTransition useDeferredValue More Advanced Hooks useSyncExternalStore useInsertionEffect useDebugValue New Hooks in React 19 and Later useActionState useFormStatus useOptimistic use useEffectEvent Bonus: ViewTransition and Fragment Refs Next.js Hooks useRouter usePathname useSearchParams useParams useLinkStatus useServerInsertedHTML Custom Hooks Common Mistakes to Avoid Cheatsheet Conclusion Performance Hooks Sometimes an update is heavy: a huge list, a slow tab, a big search result. If React does all the work at once, the page freezes. Typing feels laggy and buttons stop responding. These two Hooks let you tell React: “this update is not urgent, so do the important things first.” What is an urgent update? Anything the user expects to see instantly, like typing in a box or clicking a button. Showing the search results or opening a heavy tab can wait a moment. React can handle the urgent update first and finish the slow one in the background. useTransition useTransition lets you mark a state update as low priority. It gives you two things: isPending, which is true while the slow update is happening, and startTransition, a function you wrap around the state update. ‘use client’; import { useState, useTransition } from ‘react’; function About() { return
Hi, I write about React.
; } function SlowPosts() { // Pretend this tab is heavy: 300 rows, and each row takes a little time const rows = []; for (let i = 0; i < 300; i++) { rows.push(<SlowRow key={i} number={i + 1} />); } return- {rows}
Loading…
} {tab === ‘about’ ?- {matches.map((item) => (
- {item} ))}
{isOnline ? ‘Online’ : ‘Offline’}
; } Why not just use useEffect and useState? Because this Hook also prevents a bug called tearing, where two parts of the screen show different values of the same data during a render. Two rules to remember: Define subscribe outside your component. If it’s created inside, React will unsubscribe and subscribe again on every render. getSnapshot must return the same value when nothing changed. If it returns a brand-new object every time, you will get an infinite loop. In Next.js, getServerSnapshot is required if the component renders on the server. useInsertionEffect This one is built for people who write CSS-in-JS libraries. It runs before React changes the DOM, so a library can safely inject }; } export default function NewsletterForm() { const [state, formAction, isPending] = useActionState(subscribe, { message: ”, }); return ( ); } How it works: You pass in your function and a starting state. You put formAction on the form’s action prop. When the form is submitted, React calls your function with the previous state and the form data. Whatever your function returns becomes the new state. Notice that we don’t need onSubmit, preventDefault or a useState for every input. React reads the form data for us. Note: After the action finishes, React resets the form’s fields. That’s normal behavior in React 19. In Next.js you can pass a Server Action instead. Put it in its own file with ‘use server’ at the top, then import it: // app/actions.js ‘use server’; export async function subscribe(previousState, formData) { // save to your database here return { message: ‘Thanks for subscribing!’ }; } You might see the old name useFormState in older tutorials. It was renamed to useActionState. useFormStatus useFormStatus tells a component whether the form it sits inside is currently submitting. It’s perfect for a submit button. You import it from react-dom, not from react. ‘use client’; import { useFormStatus } from ‘react-dom’; function SubmitButton() { const { pending } = useFormStatus(); return ( ); } async function saveProfile(formData) { await new Promise((resolve) => setTimeout(resolve, 1000)); console.log(‘Saved:’, formData.get(‘name’)); } export default function ProfileForm() { return (