This roadmap is about React Developer
React Developer roadmap starts from here
Advanced React Developer Roadmap Topics
By Yevheniia B.
2 years of experience
My name is Yevheniia B. and I have over 2 years of experience in the tech industry. I specialize in the following technologies: JavaScript, API, API Integration, CSS, CSS 3, etc.. I hold a degree in Master's degree. Some of the notable projects I’ve worked on include: Geosocial Networking App, Multilingual Website for Purchasing Travel Insurance, Student Housing Rental Platform, Medical application for insurance provider. I am based in Lviv, Ukraine. I've successfully completed 4 projects while developing at Softaims.
I value a collaborative environment where shared knowledge leads to superior outcomes. I actively mentor junior team members, conduct thorough quality reviews, and champion engineering best practices across the team. I believe that the quality of the final product is a direct reflection of the team's cohesion and skill.
My experience at Softaims has refined my ability to effectively communicate complex technical concepts to non-technical stakeholders, ensuring project alignment from the outset. I am a strong believer in transparent processes and iterative delivery.
My main objective is to foster a culture of quality and accountability. I am motivated to contribute my expertise to projects that require not just technical skill, but also strong organizational and leadership abilities to succeed.
key benefits of following our React Developer Roadmap to accelerate your learning journey.
The React Developer Roadmap guides you through essential topics, from basics to advanced concepts.
It provides practical knowledge to enhance your React Developer skills and application-building ability.
The React Developer Roadmap prepares you to build scalable, maintainable React Developer applications.

What is React? React is an open-source UI library from Meta for building interfaces from reusable components.
React is an open-source UI library from Meta for building interfaces from reusable components. Teams use it for marketing sites, dashboards, and large single-page apps because it pairs a predictable programming model with a strong ecosystem.
React focuses on the view layer: routing, data fetching, and global state are usually added with libraries you choose. That keeps upgrades incremental and avoids locking you into one mega-framework unless you want one.
You describe UI as a function of state and props. When state changes, React reconciles a Virtual DOM tree against the previous tree, computes a minimal set of DOM updates, and applies them in batches.
Components compose: parents pass read-only props down, children raise callbacks up. Hooks let function components own state, effects, and memoization without class syntax.
import { useState } from 'react';
export default function Counter() {
const [n, setN] = useState(0);
return (
<button type="button" onClick={() => setN((x) => x + 1)}>
Count: {n}
</button>
);
}
What is Create React App? Create React App (CRA) is a zero-config toolchain that scaffolds React with webpack, Babel, ESLint, and Jest.
Create React App (CRA) is a zero-config toolchain that scaffolds React with webpack, Babel, ESLint, and Jest. It was the default on-ramp when teams wanted to ship without touching bundler config.
New work often starts with Vite or a meta-framework (Next.js, Remix), but many production apps still run on CRA. Knowing CRA helps you maintain legacy code and plan migrations.
The CLI copies a template and wires scripts: npm start for dev with fast refresh, npm run build for production, npm test for Jest.
Eject exposes webpack config; most teams avoid ejecting and migrate when they need SSR, monorepos, or faster cold starts.
npx create-react-app my-app
cd my-app
npm start
What is the Virtual DOM? The Virtual DOM is an in-memory tree of plain objects mirroring the UI you want.
The Virtual DOM is an in-memory tree of plain objects mirroring the UI you want. React keeps it cheap to create and diff so the real DOM is touched only when needed.
You do not install the Virtual DOM separately; it is how React represents output between renders.
On each render React builds a new element tree, compares it with the last (reconciliation), and commits the smallest DOM update set—often batched in React 18+.
This encourages declarative UI: you focus on correct state; React focuses on efficient patching. Large lists still benefit from windowing and memoization.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Clicks: {count}</p>
<button type="button" onClick={() => setCount((c) => c + 1)}>+1</button>
</div>
);
}
What is JSX? JSX is a syntax extension for writing HTML-like trees in JavaScript. Compilers turn it into React.createElement or the automatic JSX runtime.
JSX is a syntax extension for writing HTML-like trees in JavaScript. Compilers turn it into React.createElement or the automatic JSX runtime.
Colocating markup with logic makes reviews focus on behavior and accessibility instead of jumping across many file types.
Curly braces embed expressions. DOM attributes use camelCase (className, onClick). Fragments group siblings without extra nodes.
Lowercase tags are intrinsic elements; capitalized identifiers are components—hence the uppercase component name rule.
const brand = 'Softaims';
export function Hero() {
return (
<section>
<h1>Build with {brand}</h1>
</section>
);
}
What are components? Components are reusable UI pieces: functions (or classes) that return elements. Clear props and boundaries make large apps maintainable.
Components are reusable UI pieces: functions (or classes) that return elements. Clear props and boundaries make large apps maintainable.
Strong teams treat components as APIs: document props, keep side effects explicit, and test critical paths.
Function components plus Hooks are the modern default. Prefer composition—children, slots, or small presentational leaves—over deep prop drilling.
Pull data and orchestration up or into custom hooks; keep leaves easy to snapshot-test.
function Badge({ children }) {
return <span className="badge">{children}</span>;
}
export function UserRow({ user }) {
return (
<div>
<Badge>{user.plan}</Badge>
<strong>{user.name}</strong>
</div>
);
}
What are props? Props are read-only inputs from parent to child. Children must not mutate props; they call callbacks or rely on lifted state.
Props are read-only inputs from parent to child. Children must not mutate props; they call callbacks or rely on lifted state.
TypeScript interfaces (or PropTypes) document the contract and catch mistakes at build time.
React passes one props object—destructure in the signature for readability. Prefer explicit props over boolean kitchens.
Use key on lists for stable identity so reconciliation preserves state correctly.
function Price({ currency = 'USD', amount }) {
return (
<p>
{currency} {amount.toFixed(2)}
</p>
);
}
What are components in React? Components encapsulate structure, behavior, and styling boundaries.
Components encapsulate structure, behavior, and styling boundaries. They let teams scale UI by composing small, testable units instead of monolithic templates.
Functional components with Hooks are the modern default; class components remain in legacy code you may inherit.
Parents render children by nesting JSX or passing children. Props flow down; events and callbacks flow up—one-way data flow keeps mental models simple.
Split by responsibility: containers fetch and coordinate; presentational pieces stay pure where possible. Co-locate tests and stories next to complex widgets.
export function Layout({ sidebar, children }) {
return (
<div className="layout">
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
What are functional components? Functional components are plain functions that receive props and return React elements.
Functional components are plain functions that receive props and return React elements. Hooks attach state, effects, and context without class syntax or this bindings.
They are easier to test, tree-shake, and type-check, which is why Softaims defaults to them for new code.
Hooks must run unconditionally at the top level of a component or custom hook. That rule lets React preserve state across renders reliably.
Custom hooks extract reusable logic (data loading, subscriptions, form state) while keeping components readable.
import { useState } from 'react';
export function Toggle({ label }) {
const [on, setOn] = useState(false);
return (
<button type="button" aria-pressed={on} onClick={() => setOn(!on)}>
{label}: {on ? 'on' : 'off'}
</button>
);
}
What is the difference between props and state? Props are inputs owned by the parent—immutable for the child.
Props are inputs owned by the parent—immutable for the child. State is owned by the component (or lifted ancestors) and changes over time.
Mixing them up causes subtle bugs: writing to props, or storing derived data in state that could be computed.
Lift state to the lowest common ancestor when siblings need the same value. Pass both value and updater callback when children must mutate shared data.
Derive render values with plain variables or useMemo when expensive—do not duplicate props into state without a good reason.
function Temperature({ unit, value, onChange }) {
return (
<label>
{unit}
<input value={value} onChange={(e) => onChange(e.target.value)} />
</label>
);
}
What is conditional rendering? Conditional rendering chooses which elements appear based on props, state, or context—loading spinners, empty states, role-based panels, and more.
Conditional rendering chooses which elements appear based on props, state, or context—loading spinners, empty states, role-based panels, and more.
React re-runs your function; whatever JSX you return becomes the next tree to reconcile.
Use early returns for guard clauses. Inline ternaries work for small branches; extract subcomponents when branches grow.
Keep booleans meaningful (isLoading, hasError) and avoid double negatives in JSX.
function Banner({ status }) {
if (status === 'loading') return <p>Loading…</p>;
if (status === 'error') return <p role="alert">Something failed.</p>;
return <p>Ready.</p>;
}
What is composition in React? Composition builds larger UIs by nesting smaller components—often via children or explicit slot props—instead of inheritance trees.
Composition builds larger UIs by nesting smaller components—often via children or explicit slot props—instead of inheritance trees.
It matches how design systems ship layouts, cards, and dialogs with flexible interiors.
Prefer “has-a” relationships: a Modal owns focus management while children supply body content. Render props or slots pass behavior when markup must vary.
Inheritance rarely fits UI; when you need shared logic, extract hooks or utilities.
function Card({ title, children, footer }) {
return (
<article className="card">
<header><h2>{title}</h2></header>
<div className="body">{children}</div>
{footer}
</article>
);
}
What are component basics you should master?
Basics include pure render functions, explicit props, keys on lists, controlled vs uncontrolled inputs, and lifting state only when needed.
They prevent entire classes of production defects before you reach advanced patterns.
Start from a static mock, identify minimal state, then wire data top-down. Add effects only for real external synchronization—not for derived values.
Use eslint-plugin-react-hooks in CI to catch dependency mistakes early.
function Form() {
const [text, setText] = useState('');
return (
<form onSubmit={(e) => e.preventDefault()}>
<input value={text} onChange={(e) => setText(e.target.value)} />
</form>
);
}
What is rendering in React? Rendering is the phase where React calls your components to produce a React element tree describing the next UI snapshot.
Rendering is the phase where React calls your components to produce a React element tree describing the next UI snapshot.
The commit phase then applies changes to the DOM or other hosts (React Native, canvas, etc.).
State updates schedule renders. React may batch multiple setters in one event tick, so intermediate states are not always visible.
Strict Mode double-invokes render in development to surface unsafe side effects—expect logs twice locally.
import { useState } from 'react';
export default function Box() {
const [on, setOn] = useState(false);
console.log('render', on);
return <button type="button" onClick={() => setOn(!on)}>toggle</button>;
}
How do Hooks relate to rendering? Hooks like useState and useReducer enqueue updates that trigger the owning function component to render again.
Hooks like useState and useReducer enqueue updates that trigger the owning function component to render again.
Hook call order must be stable so React can match state to the correct component instance.
Calling Hooks inside loops, conditions, or nested functions breaks the internal list React maintains—lint rules catch this.
Reducer updates batch like setState; functional updaters avoid stale closures when multiple updates chain.
const [count, setCount] = useState(0);
function incTwice() {
setCount((c) => c + 1);
setCount((c) => c + 1);
}
How does conditional render interact with reconciliation? When branches mount or unmount, React creates or destroys subtree state.
When branches mount or unmount, React creates or destroys subtree state. Swapping element types at the same position resets state below that point.
That is why keys and structure matter for preserving input focus and form data.
Use keys to hint identity across lists. For tabs, sometimes lifting state out of unmounted panels preserves UX expectations.
Portals still participate in the React tree even when DOM nodes sit elsewhere.
{mode === 'list' ? (
<ListView key="list" />
) : (
<DetailView key="detail" />
)}
How do you optimize render performance? Measure first: React DevTools Profiler finds expensive subtrees. Premature memo everywhere often hides real issues like unstable props.
Measure first: React DevTools Profiler finds expensive subtrees. Premature memo everywhere often hides real issues like unstable props.
Large lists should virtualize; heavy children should lazy-load.
React.memo skips render when props are shallow-equal—pair with stable callbacks from useCallback when passing functions to pure children.
useMemo caches expensive derived values; it is not a semantic guarantee—profile to confirm benefit.
const Row = React.memo(function Row({ id, title }) {
return <tr><td>{id}</td><td>{title}</td></tr>;
});
What is lazy loading in React? React.lazy with Suspense splits code along route or feature boundaries so initial bundles stay small.
React.lazy with Suspense splits code along route or feature boundaries so initial bundles stay small.
Users download secondary screens only when they navigate to them.
Wrap lazy components with a Suspense boundary and a fallback (spinner or skeleton). Nested boundaries isolate loading states.
Combine with route-based prefetching in frameworks like Next.js for snappy transitions.
import { lazy, Suspense } from 'react';
const Reports = lazy(() => import('./Reports'));
export function App() {
return (
<Suspense fallback={<p>Loading…</p>}>
<Reports />
</Suspense>
);
}
What are React Hooks? Hooks are functions that start with use and tap into React features from function components—state, effects, context, refs, and performance helpers.
Hooks are functions that start with use and tap into React features from function components—state, effects, context, refs, and performance helpers.
They replaced most class lifecycle use-cases with smaller, composable units of logic.
Call Hooks only at the top level of React functions. Custom Hooks share behavior by calling other Hooks and returning a small API.
The exhaustive-deps lint rule keeps useEffect honest; suppressions should include a comment explaining why.
function useWindowWidth() {
const [w, setW] = useState(() => window.innerWidth);
useEffect(() => {
const h = () => setW(window.innerWidth);
window.addEventListener('resize', h);
return () => window.removeEventListener('resize', h);
}, []);
return w;
}
What is the useState hook? useState stores local state in a function component. Calling the setter schedules a re-render with the next value.
useState stores local state in a function component. Calling the setter schedules a re-render with the next value.
Functional updates like setCount((c) => c + 1) help when the next state depends on the previous.
Initial state can be a value or lazy initializer useState(() => readStorage()) so expensive work runs once.
State updates batch in event handlers; async code may need flushSync rarely for DOM reads—prefer refs or layout effects.
const [open, setOpen] = useState(false);
return <button type="button" onClick={() => setOpen((v) => !v)}>{open ? 'Close' : 'Open'}</button>;
What is the useEffect hook? useEffect runs side effects after paint: network calls, subscriptions, DOM measurements, and timers.
useEffect runs side effects after paint: network calls, subscriptions, DOM measurements, and timers.
It replaces componentDidMount, componentDidUpdate, and cleanup from componentWillUnmount in one API.
The dependency array decides when the effect re-runs. Empty array runs once on mount; omitting the array runs every render—usually a bug.
Return a cleanup function to unsubscribe or abort fetches when props change or the component unmounts.
useEffect(() => {
const id = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(id);
}, []);
What is the useContext hook? useContext reads the nearest Provider value for a React context—ideal for themes, auth session, or feature flags.
useContext reads the nearest Provider value for a React context—ideal for themes, auth session, or feature flags.
Avoid putting huge mutable objects in context without memoization; everything consuming it re-renders when the value identity changes.
Split contexts by update frequency: fast-changing data should not live beside slow-changing configuration in one object.
Combine with reducers or state machines when multiple consumers need coordinated updates.
const ThemeContext = createContext('light');
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>OK</button>;
}
What is the useReducer hook? useReducer models state transitions with a reducer function—great for multi-field forms, wizards, and undo stacks.
useReducer models state transitions with a reducer function—great for multi-field forms, wizards, and undo stacks.
Dispatch sends actions; the reducer returns the next immutable state snapshot.
Lazy initialization passes init(initialArg) as the third tuple slot for expensive setup.
For app-wide state, compare with dedicated libraries (Redux Toolkit, Zustand) when you need devtools and middleware.
function reducer(state, action) {
switch (action.type) {
case 'inc': return { count: state.count + 1 };
default: return state;
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
What is the useMemo hook? useMemo caches a computed value between renders while dependencies stay shallow-equal.
useMemo caches a computed value between renders while dependencies stay shallow-equal.
Use it for genuinely expensive pure calculations—not as a semantic guarantee for referential stability alone.
Pair with useCallback when passing callbacks to memoized children to preserve referential equality.
If dependency arrays are unstable, fix upstream data instead of adding more memo layers.
const sorted = useMemo(
() => items.slice().sort((a, b) => a.price - b.price),
[items]
);
What is the useCallback hook? useCallback returns a stable function reference when dependencies are unchanged—helpful when passing handlers into React.memo children.
useCallback returns a stable function reference when dependencies are unchanged—helpful when passing handlers into React.memo children.
It does not make the function faster by itself; it prevents unnecessary child renders.
Include every value from the rendered scope that the callback closes over—lint will guide you.
For event handlers that do not cross memo boundaries, skip useCallback to reduce noise.
const onSave = useCallback(() => {
api.save(form);
}, [form]);
What is the useRef hook? useRef holds a mutable box ( .current ) that persists for the component lifetime without triggering re-renders.
useRef holds a mutable box (.current) that persists for the component lifetime without triggering re-renders.
Common uses: DOM nodes, timers, previous props, and integrating non-React libraries.
Updating ref.current is synchronous; do not read it during render if it affects output—use state instead.
Forward refs with forwardRef when building reusable inputs or focus targets.
const inputRef = useRef(null);
function focus() {
inputRef.current?.focus();
}
return <input ref={inputRef} />;
What is client-side routing in React? Single-page apps swap views without full page reloads.
Single-page apps swap views without full page reloads. Routers map URLs to component trees, manage history entries, and lazy-load route chunks.
They integrate with data loaders, auth guards, and analytics in production apps.
Declarative routers (React Router, TanStack Router) describe routes as data. Framework routers (Next.js App Router) add server components and streaming.
Always provide fallbacks for unknown paths and preserve scroll restoration expectations for long lists.
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
{ path: '/', element: <Home /> },
{ path: '/about', element: <About /> },
]);
export function App() {
return <RouterProvider router={router} />;
}
What is React Router? React Router is the de facto routing library for React SPAs: nested routes, loaders, actions, and error boundaries integrate with data APIs.
React Router is the de facto routing library for React SPAs: nested routes, loaders, actions, and error boundaries integrate with data APIs.
v6+ favors a data-router model with loaders that run before navigation—similar mental model to Remix.
Define routes as objects or JSX. Use Outlet for nested rendering and useNavigate for imperative navigation.
Split routes with lazy() to keep initial bundles small.
What is the Next.js App Router? The App Router (Next.
The App Router (Next.js 13+) maps filesystem folders to routes, supports React Server Components, streaming, and nested layouts with shared loading UI.
It blurs the line between framework and library—React skills still apply, but data fetching defaults move to the server.
page.tsx defines UI, layout.tsx wraps segments, loading.tsx and error.tsx add boundaries. Server Actions enable mutations without bespoke API routes.
Co-locate data fetching in async Server Components where possible; push interactivity to small Client Components.
// app/dashboard/page.tsx (Server Component by default)
export default async function Page() {
const data = await fetch('https://api.example.com/metrics', {
next: { revalidate: 60 },
}).then((r) => r.json());
return <Metrics data={data} />;
}
What is TanStack Router? TanStack Router is a type-safe router for React with first-class search params, loaders, and code-splitting built around a strongly typed route tree.
TanStack Router is a type-safe router for React with first-class search params, loaders, and code-splitting built around a strongly typed route tree.
It targets teams who want router-level guarantees without adopting a full meta-framework.
Routes are defined as configuration objects; TypeScript infers params and search schemas. Integrates with TanStack Query for cached data.
Useful when you outgrow simpler client routers but are not ready to move to Next.js.
What is state management in React?
State management is how predictable data flows through your UI: local component state, lifted state, context, and external stores each fit different scopes.
The right default is often React state plus a few contexts—not every app needs Redux on day one.
Start colocated; lift when multiple siblings need the same source of truth. Add a store when undo/redo, middleware, or cross-cutting analytics appear.
Normalize remote data, keep IDs stable, and separate server cache (React Query) from UI ephemeral state.
// Local → lifted example sketch
// Child emits onChange; parent owns value
What is local state? Local state lives inside one component—forms, toggles, animations—and resets when the component unmounts unless hoisted.
Local state lives inside one component—forms, toggles, animations—and resets when the component unmounts unless hoisted.
It keeps complexity low and avoids global renders when unrelated UI updates.
Use useState or useReducer. Co-locate reducers next to components that own the transitions.
If many children need the same value, lift once—do not tunnel props through ten layers; use context or composition.
function Field() {
const [v, setV] = useState('');
return <input value={v} onChange={(e) => setV(e.target.value)} />;
}
What is the Context API? Context provides a broadcast channel so intermediate components do not manually forward props. Common uses: theme, locale, current user, feature flags.
Context provides a broadcast channel so intermediate components do not manually forward props. Common uses: theme, locale, current user, feature flags.
It is not a full replacement for Flux—frequent updates to a giant context value can re-render all consumers.
Split contexts by concern. Memoize provider values with useMemo when passing objects or callbacks.
For high-churn data, prefer external stores with selectors (Zustand, Jotai) or query caches.
const Ctx = createContext(null);
export function Provider({ children }) {
const api = useMemo(() => ({ user, signOut }), [user]);
return <Ctx.Provider value={api}>{children}</Ctx.Provider>;
}
What is Redux with React? Redux centralizes application state in a single store updated by pure reducers. Redux Toolkit is the modern standard API on top.
Redux centralizes application state in a single store updated by pure reducers. Redux Toolkit is the modern standard API on top.
It shines for large teams needing predictable updates, time-travel debugging, and middleware (logging, analytics).
configureStore wires thunk or RTK Query. Components subscribe via useSelector and dispatch actions with useDispatch.
Keep slices domain-driven; colocate RTK Query endpoints beside feature modules.
import { configureStore, createSlice } from '@reduxjs/toolkit';
const slice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: { inc: (s) => { s.value += 1; } },
});
What is Recoil? Recoil is a Facebook experimental-in-spirit state library using atoms and selectors for fine-grained subscriptions in React.
Recoil is a Facebook experimental-in-spirit state library using atoms and selectors for fine-grained subscriptions in React.
It targets graphs of derived async state without boilerplate sometimes seen in larger Redux setups.
Atoms hold state; selectors derive or async-fetch. Components subscribe only to atoms/selectors they read.
Evaluate maintenance status and team familiarity before adopting versus Redux Toolkit or Jotai.
How do you style React applications? Teams mix global CSS, CSS Modules, utility frameworks (Tailwind), CSS-in-JS, and component libraries.
Teams mix global CSS, CSS Modules, utility frameworks (Tailwind), CSS-in-JS, and component libraries. Consistency and bundle size drive the decision.
Accessibility and theming should be first-class—contrast tokens, focus rings, and reduced-motion matter.
Co-locate styles with components when possible. Use design tokens for color, spacing, and typography across products.
Avoid inline styles for static design systems; reserve them for truly dynamic values (charts, drag overlays).
/* CSS Module example */
.button { border-radius: 8px; padding: 8px 12px; }
What is Styled Components? Styled Components generates scoped CSS from template literals attached to components, enabling theming via ThemeProvider .
Styled Components generates scoped CSS from template literals attached to components, enabling theming via ThemeProvider.
Popular when teams want component-local styles with dynamic props.
Use transient props ($prop) to avoid leaking attributes to the DOM. Mind runtime cost vs zero-runtime solutions on very large pages.
What is Material UI (MUI)? MUI implements Google’s Material Design as React components with theming, accessibility defaults, and a large icon set.
MUI implements Google’s Material Design as React components with theming, accessibility defaults, and a large icon set.
It accelerates admin dashboards and internal tools where a familiar visual language helps.
Customize via createTheme and the sx prop. Prefer stable slot props over deep style overrides when upgrading versions.
What is React Bootstrap? React Bootstrap reimplements Bootstrap components without jQuery, using React-friendly props and accessibility patterns.
React Bootstrap reimplements Bootstrap components without jQuery, using React-friendly props and accessibility patterns.
Good fit when your design system already standardizes on Bootstrap tokens.
Import only components you use to limit bundle size. Pair with Sass variables for brand alignment.
What is Tailwind CSS with React? Tailwind is a utility-first CSS framework: compose small classes in JSX for rapid iteration and consistent spacing scales.
Tailwind is a utility-first CSS framework: compose small classes in JSX for rapid iteration and consistent spacing scales.
Works well with component libraries like Headless UI or Radix for accessible primitives.
Use the Prettier plugin to sort classes. Extract repeated utility clusters into small components or @apply sparingly in CSS layers.
What is Sass/SCSS with React? Sass extends CSS with variables, nesting, mixins, and modules—helpful for large design systems and shared partials.
Sass extends CSS with variables, nesting, mixins, and modules—helpful for large design systems and shared partials.
Vite and CRA can compile SCSS side-by-side with CSS Modules.
Prefer the module system (@use) over deprecated @import. Namespace variables to avoid collisions.
Keep global layers thin; push feature styles next to components.
@use 'tokens' as *;
.card {
padding: $space-3;
border-radius: $radius-md;
}
What is Ant Design? Ant Design is an enterprise-class React UI toolkit with dense data tables, forms, and internationalization utilities common in B2B apps.
Ant Design is an enterprise-class React UI toolkit with dense data tables, forms, and internationalization utilities common in B2B apps.
It ships design tokens and layout primitives tuned for admin experiences.
Tree-shake icons and locales. Customize themes with Less variables or ConfigProvider in v5+ token APIs.
What is Semantic UI React? Semantic UI React provides themable components with an emphasis on readable class semantics and accessibility helpers.
Semantic UI React provides themable components with an emphasis on readable class semantics and accessibility helpers.
Useful when teams want opinionated structure without building every primitive.
Check maintenance cadence versus MUI or Chakra for new long-term projects.
Why use component libraries? Libraries ship tested patterns for forms, dialogs, tables, and navigation—saving weeks of accessibility and keyboard work.
Libraries ship tested patterns for forms, dialogs, tables, and navigation—saving weeks of accessibility and keyboard work.
They also encode design tokens so products stay visually coherent.
Pick based on bundle budget, theming model, and TypeScript quality. Prototype in isolation before committing globally.
Wrap third-party components in your own thin adapters so migrations hurt less later.
import { Button } from '@acme/ui';
export function SaveBar() {
return <Button variant="primary">Save</Button>;
}
What is Material UI (MUI)? MUI implements Google’s Material Design as React components with theming, accessibility defaults, and a large icon set.
MUI implements Google’s Material Design as React components with theming, accessibility defaults, and a large icon set.
It accelerates admin dashboards and internal tools where a familiar visual language helps.
Customize via createTheme and the sx prop. Prefer stable slot props over deep style overrides when upgrading versions.
What is Ant Design? Ant Design is an enterprise-class React UI toolkit with dense data tables, forms, and internationalization utilities common in B2B apps.
Ant Design is an enterprise-class React UI toolkit with dense data tables, forms, and internationalization utilities common in B2B apps.
It ships design tokens and layout primitives tuned for admin experiences.
Tree-shake icons and locales. Customize themes with Less variables or ConfigProvider in v5+ token APIs.
What is Chakra UI? Chakra UI offers composable, accessible components with a style prop and theme tokens for fast customization.
Chakra UI offers composable, accessible components with a style prop and theme tokens for fast customization.
Popular for marketing sites and dashboards needing responsive layouts without heavy configuration.
Use the v2+ modular packages. Prefer semantic tokens for dark mode parity.
What is Radix UI? Radix provides unstyled, accessible primitives—dialogs, popovers, tabs—with WAI-ARIA coverage and focus management.
Radix provides unstyled, accessible primitives—dialogs, popovers, tabs—with WAI-ARIA coverage and focus management.
Pair with Tailwind or CSS Modules for branded design systems.
Compose primitives rather than overriding deeply. Use Portal-aware components for modals to avoid z-index traps.
What are headless components? Headless UI separates behavior (keyboard, ARIA, focus) from visuals. You supply markup and styles; the library supplies logic.
Headless UI separates behavior (keyboard, ARIA, focus) from visuals. You supply markup and styles; the library supplies logic.
They are ideal for design systems that must match brand guidelines exactly.
Combine with Tailwind or CSS Modules. Test with keyboard-only navigation and screen readers—logic bugs hide easily.
Radix, Headless UI, and React Aria overlap; pick based on bundle, API ergonomics, and framework integration.
import * as Dialog from '@radix-ui/react-dialog';
What is Radix UI? Radix provides unstyled, accessible primitives—dialogs, popovers, tabs—with WAI-ARIA coverage and focus management.
Radix provides unstyled, accessible primitives—dialogs, popovers, tabs—with WAI-ARIA coverage and focus management.
Pair with Tailwind or CSS Modules for branded design systems.
Compose primitives rather than overriding deeply. Use Portal-aware components for modals to avoid z-index traps.
What is Headless UI? Headless UI from Tailwind Labs ships accessible, unstyled widgets designed to pair with Tailwind classes.
Headless UI from Tailwind Labs ships accessible, unstyled widgets designed to pair with Tailwind classes.
Great when your team already standardized on Tailwind utilities.
Use Transition components for enter/leave animations. Provide meaningful labels on listbox and combobox examples.
What is React Aria? Adobe’s React Aria hooks deliver accessibility behavior for custom components—focus rings, collections, and internationalized interactions.
Adobe’s React Aria hooks deliver accessibility behavior for custom components—focus rings, collections, and internationalized interactions.
Useful when you need maximum control over DOM structure.
Compose hooks into your primitives; pair with React Spectrum components for a full design system shortcut.
What is TanStack Table? TanStack Table is headless: you render cells while the library handles sorting, filtering, grouping, and virtualization hooks.
TanStack Table is headless: you render cells while the library handles sorting, filtering, grouping, and virtualization hooks.
It scales to large datasets when paired with virtualization libraries.
Define column defs as data; keep rendering dumb for testability. Use server-side mode when datasets exceed client memory.
How does data fetching fit in React? React does not prescribe a data layer.
React does not prescribe a data layer. You can use fetch, Axios, GraphQL clients, or libraries like TanStack Query that handle caching, retries, and deduplication.
Server Components and route loaders shift some fetching off the client entirely.
Model loading and error states explicitly. Avoid fetching directly in render—use effects, loaders, or query hooks.
Align cache keys with server invalidation (tags, ETags) to prevent stale UI after mutations.
const { data, error, isLoading } = useQuery({
queryKey: ['user', id],
queryFn: () => fetch('/api/user/' + id).then((r) => r.json()),
});
What is the Fetch API in React? The browser Fetch API returns Promises for HTTP calls.
The browser Fetch API returns Promises for HTTP calls. In React, wrap calls in effects or async route loaders and store results in state or a query cache.
It is lightweight but you must handle aborting, timeouts, and JSON errors yourself.
Use AbortController to cancel in-flight requests when props change or components unmount.
Centralize base URL and auth headers in a small client module for consistency.
useEffect(() => {
const ac = new AbortController();
fetch('/api/items', { signal: ac.signal })
.then((r) => r.json())
.then(setItems)
.catch(() => {});
return () => ac.abort();
}, []);
What is Axios? Axios is a popular HTTP client with interceptors, automatic JSON transforms, and timeout support—helpful for shared API clients.
Axios is a popular HTTP client with interceptors, automatic JSON transforms, and timeout support—helpful for shared API clients.
It works in browsers and Node, making it handy for SSR apps too.
Configure an instance with base URL and auth. Interceptors centralize 401 handling and telemetry.
What is SWR? SWR from Vercel is a lightweight data-fetching library focused on stale-while-revalidate caching and realtime revalidation.
SWR from Vercel is a lightweight data-fetching library focused on stale-while-revalidate caching and realtime revalidation.
Great for dashboards that can show slightly stale data while refreshing in the background.
Define fetcher once; keys drive deduplication. Combine with suspense boundaries if using concurrent features.
What is TanStack Query? TanStack Query (formerly React Query) manages server-state: caching, background refresh, optimistic updates, and infinite queries.
TanStack Query (formerly React Query) manages server-state: caching, background refresh, optimistic updates, and infinite queries.
It reduces boilerplate compared to raw fetch in effects.
Use query keys as tuples including params. Pair mutations with invalidateQueries or precise cache updates.
How do React Server Components fetch data? Server Components run on the server, so they can await database or microservice calls directly without shipping secrets to the client.
Server Components run on the server, so they can await database or microservice calls directly without shipping secrets to the client.
The serialized RSC payload streams to the browser, shrinking client bundles.
Frameworks like Next.js wire caching and revalidation policies. Client Components still fetch for interactive widgets.
Mind waterfall requests—parallelize independent awaits or colocate loaders.
export default async function Page() {
const res = await fetch('https://api.example.com/posts', {
next: { tags: ['posts'] },
});
const posts = await res.json();
return <List posts={posts} />;
}
What are Apollo and Relay? Apollo Client and Relay are GraphQL clients for React with caches normalized by entity ID, pagination helpers, and devtools.
Apollo Client and Relay are GraphQL clients for React with caches normalized by entity ID, pagination helpers, and devtools.
They fit products where the API is GraphQL-first and schemas evolve with the UI.
Define operations colocated with components or in shared documents. Use persisted queries in production for safety and caching.
Watch bundle size—sometimes a thin fetch + generated SDK is enough for smaller surfaces.
import { gql, useQuery } from '@apollo/client';
const Q = gql`query Me { me { id name } }`;
export function Profile() {
const { data } = useQuery(Q);
return <p>{data?.me.name}</p>;
}
Why test React applications? Tests guard regressions in components that look fine manually but break edge cases—permissions, empty data, slow networks.
Tests guard regressions in components that look fine manually but break edge cases—permissions, empty data, slow networks.
Layers include unit tests for pure logic, component tests with Testing Library, and end-to-end flows with Cypress or Playwright.
Prefer testing behavior users see (roles, labels) over implementation details. Mock network at boundaries, not everywhere.
Run unit tests in CI on every PR; keep e2e suites focused on critical journeys to control flake and runtime.
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('increments', async () => {
render(<Counter />);
await userEvent.click(screen.getByRole('button', { name: /add/i }));
expect(screen.getByText(/1/)).toBeInTheDocument();
});
What is Jest? Jest is a batteries-included test runner with mocking, snapshots, and watch mode—historically the default in CRA and many Next.js templates.
Jest is a batteries-included test runner with mocking, snapshots, and watch mode—historically the default in CRA and many Next.js templates.
Use with jsdom for React component tests; pair with Testing Library queries.
Configure moduleNameMapper for CSS and assets. Keep snapshots purposeful—avoid huge JSX dumps that churn every tweak.
What is Vitest? Vitest is a Vite-native test runner with Jest-compatible APIs, fast cold starts, and ESM-first ergonomics. Ideal when your build pipeline already centers on Vite.
Vitest is a Vite-native test runner with Jest-compatible APIs, fast cold starts, and ESM-first ergonomics.
Ideal when your build pipeline already centers on Vite.
Share vite.config test settings with alias and environment. Use @vitest/ui for interactive debugging locally.
What is Cypress? Cypress drives a real browser for integration and e2e tests with time-travel debugging and network stubbing. Great for product flows: checkout, auth, onboarding.
Cypress drives a real browser for integration and e2e tests with time-travel debugging and network stubbing.
Great for product flows: checkout, auth, onboarding.
Stabilize selectors with data-testid or roles. Split fast smoke suites from long regression jobs in CI.
What is Playwright? Playwright runs cross-browser e2e tests with parallel workers, trace viewers, and codegen for authoring.
Playwright runs cross-browser e2e tests with parallel workers, trace viewers, and codegen for authoring.
Microsoft-backed; strong for CI matrices (Chromium, WebKit, Firefox).
Prefer resilient locators (getByRole). Use storageState for authenticated suites. Capture traces on first retry only to save artifacts.
What are React meta-frameworks? Meta-frameworks bundle routing, build tooling, data loading, and deployment targets—Next.js, Remix, Astro (with React islands), Gatsby, and others.
Meta-frameworks bundle routing, build tooling, data loading, and deployment targets—Next.js, Remix, Astro (with React islands), Gatsby, and others.
They trade some flexibility for faster product delivery and opinionated best practices.
Choose based on rendering model (SSR, SSG, RSC), hosting, and edge requirements. Prototype one route with real auth before committing.
Keep shared UI in packages so migrating frameworks hurts less later.
// Framework choice affects folder structure and data APIs,
// not the component model inside individual files.
What is Next.js for React teams? Next.js adds file-based routing, hybrid rendering, image optimization, and API routes—now centered on the App Router and React Server Components.
Next.js adds file-based routing, hybrid rendering, image optimization, and API routes—now centered on the App Router and React Server Components.
Vercel maintains it; self-hosting on Node or edge runtimes is supported.
Use Server Components for data-heavy views; mark interactive leaves with use client. Configure caching with tags and revalidate paths after mutations.
Measure Core Web Vitals; leverage built-in next/image and font optimization.
// app/page.tsx
export default function Page() {
return <main>Hello Next</main>;
}
What is Remix? Remix is a full-stack React framework emphasizing web standards: nested routes, loaders/actions colocated with routes, and progressive enhancement.
Remix is a full-stack React framework emphasizing web standards: nested routes, loaders/actions colocated with routes, and progressive enhancement.
Strong fit when you want forms and caching aligned with HTTP semantics.
Use defer for streaming slow promises. Deploy to any Node or edge target; adapters exist for many hosts.
What is Astro with React? Astro builds mostly static HTML and hydrates React only where you opt in—“islands” keep JS payloads small for content sites.
Astro builds mostly static HTML and hydrates React only where you opt in—“islands” keep JS payloads small for content sites.
Useful for marketing + docs with sprinkles of interactivity.
Add @astrojs/react. Mark interactive components with client directives. Prefetch intelligently to balance speed and freshness.
What is Gatsby? Gatsby is a React framework oriented to static sites and content meshes with a GraphQL data layer and rich plugin ecosystem.
Gatsby is a React framework oriented to static sites and content meshes with a GraphQL data layer and rich plugin ecosystem.
Good for documentation and marketing sites needing image pipelines and CMS connectors.
Build time can grow with large content; watch incremental builds and source plugin performance.
Compare with Next static export when evaluating new greenfield content projects.
import { graphql, useStaticQuery } from 'gatsby';
Why is Svelte on a React roadmap? Svelte compiles components to imperative DOM updates at build time—different trade-offs than React’s runtime reconciliation.
Svelte compiles components to imperative DOM updates at build time—different trade-offs than React’s runtime reconciliation.
Knowing alternatives helps you evaluate hires, migrations, and micro-frontend boundaries.
SvelteKit adds routing and SSR. Compare bundle sizes and team skill depth before mixing Svelte islands into a React host.
Interoperability is possible via micro-frontends or web components but adds operational cost.
<script>
let count = 0;
</script>
<button on:click={() => count++}>clicks: {count}</button>
How do forms work in React? Controlled inputs wire value + onChange to state; uncontrolled inputs use refs and read values on submit.
Controlled inputs wire value + onChange to state; uncontrolled inputs use refs and read values on submit.
Libraries add validation, field arrays, and async submit UX without reinventing patterns.
Debounce expensive validation. Announce errors accessibly with aria-invalid and aria-describedby.
For multi-step flows, lift step state and persist drafts when appropriate.
function Field() {
const [v, setV] = useState('');
return <input value={v} onChange={(e) => setV(e.target.value)} />;
}
What is React Hook Form? React Hook Form minimizes re-renders by registering uncontrolled inputs and validating on events—great for large forms.
React Hook Form minimizes re-renders by registering uncontrolled inputs and validating on events—great for large forms.
Integrates tightly with Zod/Yup resolvers.
Use Controller for controlled third-party widgets. Combine with error boundaries for unexpected field failures.
What is Formik? Formik is a mature form library with field helpers, validation, and submission lifecycle—popular in enterprise codebases.
Formik is a mature form library with field helpers, validation, and submission lifecycle—popular in enterprise codebases.
Compare bundle size and API ergonomics with React Hook Form for new projects.
Use FieldArray for dynamic rows. Keep validation schema colocated with forms for clarity.
What is React Final Form? React Final Form is subscription-based: components re-render only when their slice of form state changes.
React Final Form is subscription-based: components re-render only when their slice of form state changes.
Useful when profiling showed broad form re-renders as a bottleneck.
Pair with field-level validation and decorators for side effects. Evaluate maintenance vs newer libraries for greenfield.
Why validate data in React apps? Validation protects UX and security: catch bad input early, show actionable errors, and align client checks with server rules.
Validation protects UX and security: catch bad input early, show actionable errors, and align client checks with server rules.
Schema libraries share types between client and API layers when using TypeScript.
Validate on blur for long forms, on submit for short ones. Never trust client-only validation—duplicate rules server-side.
Compose schemas for nested objects and discriminated unions to model real APIs.
const schema = z.object({
email: z.string().email(),
});
What is Zod? Zod is a TypeScript-first schema library with great inference—popular with React Hook Form and tRPC. Parse unknown JSON at boundaries instead of casting blindly.
What is Yup? Yup provides schema validation often paired with Formik. It supports conditional tests and async validations.
Yup provides schema validation often paired with Formik. It supports conditional tests and async validations.
Mature ecosystem; compare with Zod for TypeScript inference needs.
Define reusable schema fragments for addresses, payments, etc. Memoize schema instances when created in render.
What is Joi? Joi is a classic JavaScript schema validator common in Node APIs; some teams reuse similar shapes on the client.
Joi is a classic JavaScript schema validator common in Node APIs; some teams reuse similar shapes on the client.
Great when your backend already standardizes on Joi and you want parallel rules.
Keep browser bundles lean—often validate on server and send field errors to React forms.
How do animations fit in React? Animations guide attention, show state changes, and improve perceived performance—modals, lists, route transitions.
Animations guide attention, show state changes, and improve perceived performance—modals, lists, route transitions.
Pick CSS transitions, Web Animations API, or libraries when you need orchestration and gesture physics.
Respect prefers-reduced-motion. Avoid animating layout thrashing properties (width/height) when transform/opacity suffices.
Test on low-end devices; defer heavy animation code with dynamic import.
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.01ms !important; }
}
What is Framer Motion? Framer Motion offers declarative animations, gestures, and layout transitions in React with a friendly API.
Framer Motion offers declarative animations, gestures, and layout transitions in React with a friendly API.
Common for marketing pages and interactive dashboards.
Use layout props carefully—profile list animations. Lazy-load for below-the-fold sections.
What is React Spring? React Spring is a spring-physics-based animation library that interpolates values over time—great for natural motion. Works well with three.js and SVG.
What is Lottie for React? Lottie renders After Effects animations exported as JSON—handy for polished loaders and empty states.
What is GSAP? GSAP is a high-performance animation engine used for timelines, SVG morphing, and scroll-driven scenes.
GSAP is a high-performance animation engine used for timelines, SVG morphing, and scroll-driven scenes.
Often paired with React via refs rather than fighting the render cycle.
Use useLayoutEffect when measuring DOM for animations. Kill timelines on unmount to prevent leaks.
What is Anime.js? Anime.js is a lightweight animation library for CSS properties, SVG, and JS objects—good for smaller interactions.
How does React power mobile apps? React Native renders native views using JavaScript and React patterns on iOS and Android. Expo accelerates tooling, builds, and OTA updates.
React Native renders native views using JavaScript and React patterns on iOS and Android. Expo accelerates tooling, builds, and OTA updates.
Code sharing with web depends on architecture—business logic often shares; view layers diverge.
Mind bridge costs between JS and native modules. Profile lists with FlatList virtualization.
Plan navigation (React Navigation), push notifications, and store policies early.
import { Text, View } from 'react-native';
export function Hello() {
return (
<View>
<Text>Hello native</Text>
</View>
);
}
What is React Native? React Native maps React components to platform widgets, enabling near-native UX with JavaScript tooling.
React Native maps React components to platform widgets, enabling near-native UX with JavaScript tooling.
Use TypeScript, Flipper/React Native Debugger, and platform-specific files when needed.
Hermes improves startup on Android. Watch native dependency upgrades when Xcode/Android SDK versions move.
What is Expo? Expo provides managed workflows, EAS Build, and modules for camera, notifications, and updates—speeding delivery for many teams.
Expo provides managed workflows, EAS Build, and modules for camera, notifications, and updates—speeding delivery for many teams.
Custom native code is possible via config plugins or ejecting to bare workflow.
Use Expo Router for file-based navigation aligned with web mental models.
What is React Navigation? React Navigation is the standard routing library for React Native with stack, tab, and drawer navigators.
React Navigation is the standard routing library for React Native with stack, tab, and drawer navigators.
Deep linking and typed params improve production quality.
Reset stacks thoughtfully after auth changes. Test Android back behavior against user expectations.
What is NativeBase? NativeBase provides cross-platform UI primitives themed for mobile—buttons, forms, and layout utilities. Evaluate bundle impact versus fully custom screens.
Why Redux on mobile React stacks? Some React Native apps mirror web architecture with Redux Toolkit for predictable global state—especially with shared business logic.
Some React Native apps mirror web architecture with Redux Toolkit for predictable global state—especially with shared business logic.
Others prefer Zustand, Jotai, or React Query depending on data shape.
Keep stores slice-oriented. Use RTK Query for REST/GraphQL caches instead of duplicating fetch logic in reducers.
Persist selectively (redux-persist) with encryption for sensitive tokens.
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore({ reducer: { /* slices */ } });
What is server-side rendering with React? SSR sends HTML from the server so first paint arrives with content—helpful for SEO, social previews, and slow devices.
SSR sends HTML from the server so first paint arrives with content—helpful for SEO, social previews, and slow devices.
Hydration attaches client React to that HTML; mismatches cause expensive fixes.
Streaming SSR sends chunks progressively. Avoid browser-only APIs during server render—guard with typeof window or dynamic import.
Frameworks automate routing and data loading; raw renderToString is rare in new apps.
import { renderToString } from 'react-dom/server';
const html = renderToString(<App />);
What is ReactDOMServer? react-dom/server exposes renderToString , renderToPipeableStream , and related APIs to emit HTML from a React tree.
react-dom/server exposes renderToString, renderToPipeableStream, and related APIs to emit HTML from a React tree.
Frameworks wrap these; custom Node servers use them for bespoke SSR.
Streaming APIs support Suspense boundaries—send shells first, resolve async components later.
Always escape user content; React handles text nodes, but raw HTML insertion needs sanitization.
import { renderToPipeableStream } from 'react-dom/server';
How do you SSR React with Express? Express (or Fastify) can call React server render inside route handlers, then send HTML with asset links and hydration state.
Express (or Fastify) can call React server render inside route handlers, then send HTML with asset links and hydration state.
You own routing, caching, and deployment—flexible but more maintenance than a framework.
Split vendor bundles; send hydration script after HTML. Consider load balancing and template caching for throughput.
Use streaming responses for large pages; handle errors with fallback HTML.
app.get('*', (req, res) => {
const stream = renderToPipeableStream(<App url={req.url} />, {
onShellReady() {
res.setHeader('content-type', 'text/html');
stream.pipe(res);
},
});
});
When is SSR worth the complexity?
SSR improves first meaningful paint for content-heavy pages, supports crawlers that execute limited JS, and can simplify auth for first load in some architectures.
It adds server cost, caching discipline, and hydration constraints.
Measure: compare LCP and TTFB before vs after. Sometimes static generation plus edge caching beats full SSR.
Pair with CDN caching and stale-while-revalidate headers for scale.
// Decision checklist:
// - SEO critical? - Dynamic per user? - Edge or origin SSR?
