React
100 questions
What is React and what problems does it solve?
•React is a UI library.
•Solves the problem of declarative interface description.
•UI = function of state.
•Simplifies component composition.
•Works well with the ecosystem (Router, state, build).
How does React differ from a framework?
•React is only the UI layer.
•Routing/data/architecture are chosen separately.
•Frameworks (Next/Remix) impose more rules.
•React is more flexible but requires decisions.
•Larger projects often choose a framework.
What is JSX and how does it work?
•JSX is a syntax similar to HTML in JS.
•Compiled into React.createElement calls.
•You can write expressions {expr} inside.
•Attributes are props.
•Must have one root element (or Fragment).
Why is the key prop needed in lists?
•key helps React match elements between renders.
•Speeds up diff and reduces bugs.
•key should be stable, not an index (if list changes).
•Better to use id from data.
•Incorrect key causes 'jumping' state.
What is a component and what types of components are there?
•A component is a function/class returning UI.
•Functional components are standard today.
•Class components are found in legacy code.
•Components are 'containers' and 'presentational'.
•Composition is more important than inheritance.
What are props and how to use them correctly?
•props are input data for a component.
•props are immutable (read-only).
•Pass callbacks to change behavior.
•Keep props minimal and clear.
•Use default values via function parameters.
What is state and when is it needed?
•state is internal component state.
•Use for data that changes over time.
•Keep state as close as possible to where it's used.
•Do not duplicate computed data in state.
•For shared state — lift up or use a store.
How does useState work and why is setState asynchronous?
•useState returns a value and a setter.
•setState schedules an update and re-render.
•Updates can be batched.
•To depend on the previous value, use a function: setX(prev => ...).
•Do not rely on instant change after setState.
How to update objects and arrays in state without mutations?
•Do not mutate state directly.
•Object: setS(prev => ({ ...prev, a: 1 })).
•Array: setA(prev => [...prev, item]).
•For deletion: filter.
•For complex structures, you can use immer.
What is derived state and why is it harmful?
•Derived state is when state duplicates a computed value.
•It leads to desynchronization.
•It's better to compute via useMemo or directly in render.
•Store the source of truth once.
•Exception — when you need to 'fix' a value in time.
What is lifting state up and when should you do it?
•Moving state to a common parent.
•Needed when multiple components need a single source of truth.
•Parent holds state and passes props down.
•Children call callbacks for changes.
•Alternative — context/store if the tree is large.
How does useEffect work and what is it used for?
•useEffect performs side effects after rendering.
•Suitable for subscriptions, requests, DOM manipulation.
•Dependencies are set with an array deps.
•Returning a function — cleanup.
•Do not use useEffect for computing derived state.
How to correctly specify dependencies for useEffect?
•List all values used inside the effect.
•Do not disable eslint rules without reason.
•Use useCallback for functions.
•Use useMemo for objects.
•If the effect is too 'noisy' — reconsider the architecture.
What is the difference between useEffect and useLayoutEffect?
•useEffect runs after the browser paints.
•useLayoutEffect runs synchronously after DOM mutations, before painting.
•useLayoutEffect can block rendering.
•Use it for measurements/UI flickering.
•In most cases, useEffect is sufficient.
Why should hooks not be called conditionally?
•React relies on the order of hook calls.
•Conditional calls break the order.
•This causes bugs and incorrect state.
•Rule: hooks only at the top level of the component.
•Move condition inside hook/effect.
What is useMemo and when is it useful?
•useMemo caches the result of a computation.
•Needed for expensive calculations or stable references.
•Does not replace rendering optimization everywhere.
•Watch deps, otherwise it will be stale.
•Often useful before passing to memo/effects.
What is useCallback and how does it differ from useMemo?
•useCallback caches a function.
•useMemo caches a value.
•useCallback(fn, deps) ~= useMemo(() => fn, deps).
•Useful for passing callbacks to memo components.
•Do not overuse: it also has overhead.
When does memo really help, and when does it not?
•Memo is useful if a component re-renders frequently with the same props.
•If props always change (new objects) — little benefit.
•Optimization requires measurements (profile).
•Memo increases complexity.
•First, optimize architecture and state.
What is React.memo and how does it work?
•Wraps a component and skips re-rendering if props haven't changed (shallow).
•Shallow comparison.
•You can pass a custom comparison function.
•Stabilize props (useMemo/useCallback).
•Don't forget about context: it will still cause re-rendering.
Why is it dangerous to optimize React 'by eye'?
•The problem is often not where it seems.
•useMemo/useCallback can worsen performance.
•You need React DevTools profiler.
•Measure before/after.
•Optimization should be justified.
What is reconciliation in React?
•It's the algorithm for comparing the old and new tree.
•React tries to minimize DOM changes.
•key in lists affects reconciliation.
•Changing component type => unmount/mount.
•Tree structure is important for performance.
What is virtual DOM and why is it not 'magic'?
•Virtual DOM is an object representation of UI.
•React compares trees and applies patches.
•The gain is not in speed, but in the convenience of declarative UI.
•The real cost is rendering and comparison.
•Proper state management is more important.
Why does a component re-render and how to understand it?
•Re-rendering due to changes in state/props/context.
•Parent re-render doesn't always mean DOM update.
•Use React DevTools Profiler.
•For debugging, temporarily add logs.
•Check stability of props and state selectors.
What are controlled components (controlled forms)?
•Input field managed by state.
•value and onChange link UI and data.
•Provides validation and control.
•Can be slower on large forms.
•Alternative — uncontrolled + refs/forms and libraries.
How to make uncontrolled input and when is it justified?
•Use defaultValue instead of value.
•Read value via ref on submit.
•Suitable for large forms where performance matters.
•Do validation on submit/blur.
•React Hook Form often uses this approach.
How to handle events correctly in React?
•Events are SyntheticEvent (most cases).
•Use onClick/onChange, etc.
•Don't call handler immediately: onClick={() => ...}.
•For performance, define handler in a function.
•Remember about bubbling and stopPropagation.
How does SyntheticEvent differ from native events?
•It's a wrapper over the native event.
•Provides a unified API across browsers.
•In older versions, pooling was used, now less of an issue.
•event.nativeEvent gives the native event.
•Usually, SyntheticEvent is enough.
How to work with refs properly and when are they needed?
•refs provide access to the DOM/instance.
•Needed for focus, measurements, integration with libraries.
•Do not use refs for data instead of state.
•useRef stores a mutable value without causing re-render.
•To forward a ref, use forwardRef.
What is forwardRef and when is it needed?
•forwardRef allows passing a ref inside a component.
•Needed for component libraries.
•Simplifies focus and integrations.
•Try not to leak DOM details unnecessarily.
•Type the ref explicitly in TS.
What is useImperativeHandle and should you use it?
•Allows customizing the ref API.
•Useful for controls (focus, reset).
•This is an imperative approach, use rarely.
•Prefer declarative props.
•If used — document the methods.
What is the Context API and what are its limitations?
•Context passes data through the tree without props.
•Good for theme, locale, auth.
•Frequent context changes can rerender many components.
•Use separate contexts and memoization.
•For complex cases, a store with selectors is better.
How to avoid unnecessary rerenders due to Context?
•Create multiple contexts instead of one large.
•Pass primitives or memoized objects.
•Wrap providers closer to consumers.
•Move logic to store/selectors.
•Check with a profiler.
What are custom hooks and why are they needed?
•These are functions that use hooks and reuse logic.
•They simplify behavior composition.
•They make components thin.
•The name should start with use.
•Follow hook rules inside.
How to design custom hooks to make them reusable?
•Keep the API minimal: inputs and outputs.
•Do not tie the hook to a specific UI.
•Return data and callbacks.
•Do not hide side effects.
•Document expectations and edge cases.
What is React Router and what alternatives are there?
•React Router is a popular router for SPA.
•Alternatives: Next.js routing, Remix routing.
•For mobile: React Navigation.
•Choice depends on SSR/SPA and requirements.
•In large projects, data APIs and loaders are important.
What are SSR, CSR, and SSG (in the context of React)?
•CSR — rendering in the browser.
•SSR — HTML is rendered on the server.
•SSG — HTML is generated at build time.
•SSR improves SEO and FCP but is more complex.
•SSG is good for content but requires data regeneration.
What is hydration and what problems can occur?
•Hydration — 'bringing to life' SSR HTML in the browser.
•React compares the markup and attaches handlers.
•Mismatch of data => hydration mismatch.
•Avoid random values during initial render (Date.now).
•Separate server/client components (in Next).
Why does hydration mismatch happen and how to fix it?
•Different HTML on server and client.
•Reasons: time, random, access to window, conditional branches.
•Use client-only rendering via useEffect or dynamic import.
•Keep data consistent (prefetch).
•Check environment (typeof window).
How to safely use window/document in React?
•In SSR, window is unavailable.
•Access inside useEffect or check typeof window !== 'undefined'.
•Use subscriptions and cleanup for window sizes.
•Consider SSR for cookies/localStorage.
•In Next 13+, use client components.
How to work with data fetching in React?
•Basic: fetch in effect + state.
•Important: cancel requests (AbortController).
•Handle loading/error.
•For cache/re-fetch, better TanStack Query.
•In SSR frameworks, use server loaders.
How to properly handle loading/error/empty states?
•Show skeleton/spinner for loading.
•For error — clear message + retry.
•For empty — separate UI and CTA.
•Don't mix data fetching logic and display.
•Keep state explicit (discriminated union).
How to cancel requests and avoid race conditions?
•Use AbortController and signal in fetch.
•Call abort in cleanup effect.
•Store requestId and ignore outdated responses.
•Use libraries with request deduplication.
•Don't call setState after unmount.
What is Suspense and what is it used for?
•Suspense allows showing fallback while resource loads.
•Mainly used for lazy and data in frameworks.
•Suspense boundary localizes loading.
•Doesn't replace error handling — need Error Boundary.
•Ecosystem support depends on data fetching stack.
How does React.lazy and code splitting work?
•React.lazy loads component dynamically.
•Use with <Suspense fallback>.
•Split by routes/heavy widgets.
•Don't split too finely — many chunks are harmful.
•Enable analysis in bundler (bundle analyzer).
What is Error Boundary and why is it needed?
•Catches errors during rendering/lifecycle.
•Doesn't catch errors in async/handlers.
•Shows fallback UI.
•Implemented via class component or library.
•Add logging (Sentry) in componentDidCatch.
How to create forms and validation in React?
•Small forms with useState.
•Larger ones — better React Hook Form.
•Validate with schema (zod/yup).
•For UX: validate onBlur or debounce.
•Show errors near field and overall.
What is React Hook Form and why is it popular?
•Minimizes re-renders.
•Uses uncontrolled inputs by default.
•Easy integration with schemas.
•Scales well for large forms.
•Less boilerplate than manual solutions.
How to implement debounce for search/input?
•Use setTimeout/clearTimeout in useEffect.
•Or the lodash.debounce library.
•Store raw value separately from the applied one.
•Consider request cancellation.
•Don't forget cleanup.
How to manage focus and accessibility (a11y) in React?
•Use semantic elements (button, label).
•Manage focus via ref.
•In modals, implement focus trap.
•Add aria-* attributes only when needed.
•Test with keyboard and screen reader.
How to correctly implement a modal window?
•Render via portal (at the end of body).
•Close on Esc and overlay click.
•Block scroll of the background.
•Maintain focus trap and return focus.
•Handle accessibility (role='dialog').
What is a Portal and when is it needed?
•Portal renders children into another DOM node.
•Needed for modals, tooltips, dropdown menus.
•Avoids overflow/z-index issues.
•Events still bubble through React tree.
•Watch for accessibility.
How does batch updates work in React?
•React can combine multiple setState calls into one render.
•This reduces re-renders.
•In React 18, batching works even in async contexts.
•Don't rely on the order of setters without functional form.
•For synchronous reads, use useEffect after render.
What is concurrent rendering in React 18?
•The ability to interrupt and continue rendering.
•Improves UI responsiveness.
•Doesn't mean automatic acceleration.
•Requires correct priorities (transitions).
•Possible bugs with incompatible libraries.
What is useTransition and when is it useful?
•Allows marking updates as low priority.
•UI remains responsive during heavy updates.
•Returns isPending for UI state.
•Useful for filters/sort toggles.
•Doesn't replace data optimization.
What is useDeferredValue and how does it differ from debounce?
•Deferred value for low priority.
•Doesn't delay events but allows rendering later.
•Good for searching large lists.
•Debounce delays calls, deferred prioritizes rendering.
•Use consciously in combination.
How to properly write keys and identifiers for components?
•key is only needed for lists.
•Use stable IDs from data.
•Don't use random/Date.now for key.
•Don't use index if items can move/delete.
•Bad key breaks local state preservation.
How to work with event handler lifting?
•Handler is stored higher where state exists.
•Child component calls props.onAction(data).
•Simplifies testing.
•Don't pass too many callbacks — group actions.
•For complex scenarios, use reducer.
What is useReducer and when to choose it over useState?
•useReducer is suitable for complex state.
•When there are many actions and transitions.
•Simplifies testing (reducer as a pure function).
•Works well with discriminated unions.
•Can be used for forms and complex UI.
How to design a reducer: actions and types?
•Actions as union: { type: 'add', payload: ... } | ....
•Do exhaustive check in switch.
•Keep the reducer pure without side effects.
•Move side effects to effects or middleware (in store).
•Write tests for each action.
How to avoid prop drilling?
•Lift components closer to each other.
•Use composition (children) and render props.
•Use Context for truly global state.
•Use store for complex shared state.
•Do not turn Context into a trash heap.
What are children and how to use composition?
•children are nested content of a component.
•Allows building composition (Layout, Card).
•Makes API flexible.
•Can be combined with render props.
•Avoid overly complex abstractions.
What are render props and when is it useful?
•This pattern: prop is a function returning UI.
•Allows sharing logic.
•Now often replaced by hooks.
•Useful for library components.
•Watch out for performance (new function on each render).
What are compound components and where are they used?
•A set of related components (Tabs, Menu).
•Shared state stored in parent component.
•Children read state via context.
•Provides convenient API and composition.
•Requires careful typing and docs.
How to type props in React + TypeScript?
•Describe type/interface Props.
•function C(props: Props) {}.
•For children: React.ReactNode.
•For onClick: (e: React.MouseEvent) => void.
•Do not abuse React.FC if not needed.
How to type components that accept a component/icon?
•Accept React.ComponentType<Props>.
•For icons often: React.ComponentType<React.SVGProps<SVGSVGElement>>.
•Or specific library type (LucideIcon).
•Keep props minimal.
•Do not accept any for components.
How to test React components?
•Main approach: React Testing Library.
•Test behavior, not implementation details.
•Use user-event for real scenarios.
•Mock network and external dependencies.
•E2E (Playwright/Cypress) for key flows.
What to test: unit, integration, or e2e?
•Unit — pure functions/reducers.
•Integration — components with interaction.
•E2E — critical user flows.
•Do not try to cover everything with e2e.
•Balance depends on risk and testing cost.
How to mock fetch/HTTP requests in tests?
•For fetch, you can use MSW.
•MSW mocks at the network level (realistic).
•For unit tests, you can mock the client (axios).
•Watch out for resetting mocks between tests.
•Check loading/error states.
What is StrictMode and why can effects be called twice in dev?
•StrictMode enables additional checks in dev.
•It may run effects twice to detect bugs.
•This does not happen in production.
•Write effects to be idempotent and with cleanup.
•Do not use StrictMode as a bug in production.
How to properly log and debug React?
•Use React DevTools.
•Use Profiler for performance.
•Set breakpoints in handlers and effects.
•For complex bugs — minimal reproducible example.
•Do not leave console.log in production.
How to work with URL state (query params) in React?
•URL is also application state.
•Synchronize filters/pagination with query.
•Use router API (React Router/Next).
•Handle absence of parameters with defaults.
•Do not do setState in useEffect unnecessarily.
How to store authorization tokens in a React app?
•Do not store tokens in localStorage if XSS risk is high.
•Prefer httpOnly cookies (if possible).
•Separate auth state and user profile.
•Add refresh tokens via backend protocol.
•Log out and handle 401/403 responses.
How to protect against XSS in React?
•React escapes strings by default.
•It is dangerous to use dangerouslySetInnerHTML.
•Sanitize HTML with DOMPurify.
•Do not insert raw user input into HTML.
•CSP and secure headers are also important.
When to use dangerouslySetInnerHTML and how to do it more safely?
•Use only if rendering HTML (markdown).
•Sanitize content.
•Limit supported tags.
•Avoid inline scripts and event handlers.
•Think about CSP.
How to properly work with styles in React?
•Options: CSS Modules, Tailwind, styled-components, plain CSS.
•Choose based on team and project.
•Keep styles close to component, but do not mix logic.
•Watch for specificity and overrides.
•For design systems, it’s convenient to have components and tokens.
How to organize folders and architecture of a React project?
•Feature-oriented structure is usually better.
•Separate UI, hooks, services, types.
•Keep business logic outside components.
•Avoid overly large components.
•Set rules for imports and module boundaries.
What is container/presentational pattern and is it still relevant?
•Container handles data and logic, presentational handles UI.
•Helps separate responsibilities.
•Now often implemented via hooks.
•Useful in large teams.
•Do not enforce strict structure if the project is small.
How to avoid memory leaks in React?
•Clear subscriptions in the cleanup effect.
•Cancel requests on unmount.
•Do not store large objects in global state unnecessarily.
•Watch for listeners on window/document.
•Use profiling and DevTools.
Why can't you call setState after unmount and how to avoid it?
•The component is already unmounted, update is unnecessary.
•It causes warnings and potential leaks.
•Cancel async operations in cleanup.
•Use AbortController or ignore outdated responses.
•Data libraries handle this automatically.
How to properly work with setTimeout/setInterval timers?
•Set the timer in useEffect.
•Clear it in cleanup (clearTimeout/clearInterval).
•For interval, consider stale closures (useRef).
•Do not create a timer on every render.
•For complex logic, create a custom hook.
What are stale closures in hooks and how to avoid them?
•Closure can hold onto old values.
•Commonly occurs in setInterval/handlers.
•Add dependencies or use functional setState.
•Store current value in useRef.
•Do not ignore deps for linter silence.
Why can setState in a loop/multiple times behave unexpectedly?
•Updates are batched.
•The value may be outdated.
•Use functional updates.
•Combine sequential changes into one setState.
•For complex scenarios, prefer reducer.
How to properly pass functions down the tree?
•Stabilize callbacks with useCallback if important.
•Do not overuse useCallback without profiling.
•Group callbacks into a memoized actions object.
•Use context/store for global actions.
•Ensure UI components remain simple.
What is dependency inversion in React UI?
•Component depends on abstraction (props), not directly on service.
•Pass loading/saving functions as dependencies.
•Simplifies testing.
•Simplifies replacing API implementation.
•Especially useful in large projects.
When to use a global state manager (Redux/Zustand/Jotai)?
•When many screens use the same data.
•When caching, selectors, devtools are needed.
•When prop drilling becomes problematic.
•Do not use store for local UI state.
•Evaluate the cost of onboarding and team training.
Redux vs Zustand: what to choose?
•Redux is good for large teams and strict patterns.
•Redux Toolkit reduces boilerplate.
•Zustand is simpler and has less code.
•Zustand is suitable for UI and small stores.
•Choice depends on middleware/ ecosystem requirements.
What is a selector and why is it important for performance?
•Selector selects a part of the state.
•Reduces re-renders if the component subscribes only to what it needs.
•In Redux — reselect/memoized selectors.
•In Zustand — selector in useStore.
•Selectors help keep components narrow.
How to avoid re-rendering a large list (1000+ items)?
•Use virtualization (react-window/react-virtual).
•Keep elements simple.
•Stabilize the key.
•Do not perform heavy computations during rendering.
•Divide the list into memoized elements.
What is virtualization and how does it work?
•Only the visible part of the list is rendered.
•Other elements are replaced with empty space.
•Significantly reduces DOM load.
•Requires fixed/measurable element sizes.
•Good for tables and logs.
How to optimize table rendering in React?
•Virtualization of rows/columns.
•Memoization of cells and columns.
•Stable callbacks and data.
•Separate sorting/filtering state.
•Consider ready-made libs (TanStack Table).
How to properly handle errors in asynchronous handlers?
•try/catch inside async handler.
•Show user-friendly message.
•Log details in monitoring.
•Do not leave errors silent.
•Use a centralized client for requests.
What is react-query (TanStack Query) and when is it needed?
•Manages server state: cache, refetch, deduplication.
•Simplifies loading/error states.
•Has invalidation and optimistic updates.
•Eliminates much manual code.
•Does not replace client-side state for UI.
What is optimistic update and what are the risks?
•UI updates before server response.
•Improves UX.
•Need to be able to rollback on error.
•Watch out for competing requests.
•Data libraries help implement correctly.
How to implement pagination and infinite scroll?
•Pagination: page/pageSize in URL and requests.
•Infinite scroll: load on scroll/IntersectionObserver.
•Watch for repeated requests and deduplication.
•Show loader and end of list indicator.
•Virtualization is often needed together with infinite scroll.
How to use IntersectionObserver in React?
•Create a ref on the sentinel element.
•In an effect, create an observer and subscribe.
•In callback, trigger loading of the next page.
•Don't forget cleanup: disconnect.
•Consider dependencies and stale closures.
How to properly work with localization (i18n) in React?
•Use a library (react-i18next).
•Store keys, not strings, in code.
•Watch for date/number formatting (Intl).
•Do not concatenate strings manually.
•Plan for plural rules and context.
How to implement theming (dark/light) in React?
•Store theme in context/store.
•Save choice in localStorage/cookie.
•Consider prefers-color-scheme.
•Use variables or Tailwind for CSS.
•Do not break SSR: initial theme should be consistent.
How to implement error and performance monitoring?
•Connect Sentry or an equivalent tool.
•Log errors from Error Boundary.
•Add performance tracing.
•Mark releases and sourcemaps.
•Do not send PII unnecessarily.
What are common beginner mistakes in React?
•Mutate state.
•Derive state and sync via useEffect.
•Forget key and deps.
•Store too much in global state.
•Optimize without measurements.
Practical rules for maintainable React code?
•Keep components small and responsible for one thing.
•Keep state close to where it is used.
•Separate server-state and UI-state.
•Write tests for critical scenarios.
•Optimize based on profiling, not feelings.