Skip to content

Easy React JS Interview Questions

60 easy questions with answers. Definitions and fundamentals every candidate must answer quickly and correctly.

Topics in the easy set

React Fundamentals: 13 Props and State: 10 Routing and Forms: 9 Testing and Debugging: 8 State Management: 6 React Hooks: 5 Performance Optimization: 5 Next.js and Advanced React: 4
Solved — easyStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is React and why is it so widely used for building web interfaces?

Save to ▾
Show answer
React is an open-source JavaScript library for building user interfaces from reusable components. You describe what the UI should look like for a given state and React updates the DOM efficiently when that state changes. It is popular because of its component model, huge ecosystem, strong job market, React Native for mobile, and frameworks like Next.js that add routing and server rendering on top.
02

What is JSX and how does the browser understand it?

Save to ▾
Show answer
JSX is a syntax extension that lets you write HTML-like markup inside JavaScript. Browsers cannot run JSX directly, so a compiler such as Babel, SWC or esbuild (used by Vite) transforms it into calls like jsx('div', props) from react/jsx-runtime. JSX is just expressions, so you can embed values with curly braces, but attributes use camelCase names like className and onClick.
03

Explain the Virtual DOM and reconciliation in React.

Save to ▾
Show answer
The Virtual DOM is a lightweight JavaScript tree describing the UI. When state changes, React renders a new tree, compares it with the previous one (reconciliation, or diffing) and applies only the minimal real DOM changes. It assumes elements of different types produce different trees and uses keys to match list items, which makes the diff roughly linear instead of very expensive full tree comparison.
04

What is the difference between functional components and class components?

Save to ▾
Show answer
Class components extend React.Component, use this.state and lifecycle methods like componentDidMount. Functional components are plain functions that return JSX and use hooks such as useState and useEffect for state and side effects. Modern React code is written almost entirely with functional components because they are shorter, easier to test and reuse logic through custom hooks. Class components are still needed only for error boundaries.
05

What are keys in React lists and why are they required?

Save to ▾
Show answer
A key is a stable, unique identifier given to each element in a list so React can tell which items were added, removed or moved between renders. Without good keys React may reuse the wrong DOM nodes or component state. Use an id from your data, for example key={user.id}. Keys only need to be unique among siblings, not across the whole app.
06

How do you return multiple elements from a component without adding an extra div?

Save to ▾
Show answer
Use a Fragment. The short syntax <>...</> groups children without adding a DOM node. Use the long form when you need a key, for example inside a map. function Row({ item }) { return ( <> <td>{item.name}</td> <td>{item.price}</td> </> ); } items.map(i => <React.Fragment key={i.id}>...</React.Fragment>)
07

Show the common ways to do conditional rendering in React.

Save to ▾
Show answer
You can use if statements before return, the ternary operator, or logical AND. Be careful with && and numbers, because 0 is rendered. function Status({ user, count }) { if (!user) return <Login />; return ( <div> {user.isAdmin ? <AdminPanel /> : <Dashboard />} {count > 0 && <Badge count={count} />} </div> ); }
08

What does one-way data flow mean in React?

Save to ▾
Show answer
Data in React flows down from parent to child through props. A child cannot directly change its parent's data; instead the parent passes a callback function, and the child calls it to request a change. This makes the app predictable because you can trace where every value comes from. Two-way binding, as in some other frameworks, is done manually with value and onChange.
09

Your manager asks you to set up a new React project in 2026 and suggests Create React App. What would you recommend?

Save to ▾
Show answer
The React team deprecated Create React App in 2025. For a single-page app, use Vite (npm create vite@latest, choose React with TypeScript), which gives very fast dev server and builds. For full-stack apps with routing, SSR and server components, the React docs recommend a framework such as Next.js or React Router in framework mode. Choose based on whether you need server rendering and SEO.
10

You import a component and get the error 'Element type is invalid: expected a string or a class/function but got undefined'. How do you debug it?

Save to ▾
Show answer
This almost always means the import does not match the export. If the file uses export default Header, import it as import Header from './Header'. If it uses export function Header, import it as import { Header } from './Header'. Also check the file path, circular imports and that the component name starts with a capital letter. Logging the imported value quickly confirms it is undefined.
11

Write a simple counter component with increment, decrement and reset buttons.

Save to ▾
Show answer
A counter is the classic useState example. Use the functional updater so each click works on the latest value. import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); return ( <div> <h2>{count}</h2> <button onClick={() => setCount(c => c + 1)}>+</button> <button onClick={() => setCount(c => c - 1)}>-</button> <button onClick={() => setCount(0)}>Reset</button> </div> ); }
12

Tell me about a React project you built and the hardest problem you solved in it.

Save to ▾
Show answer
Situation: in my final year I built a hostel complaint portal with React, Vite and a Node API. Task: the complaint list became slow and buggy when filters changed. Action: I found I was storing filtered data in state and syncing it with effects, so I derived it during render with useMemo and fixed missing keys. Result: bugs disappeared, the page felt instant, and I learned to keep state minimal.
13

React changes fast. How do you keep your skills current?

Save to ▾
Show answer
I follow the official react.dev blog and docs, read release notes for React, Next.js and the libraries we use, and try new features in a small side project before using them at work. For example, when React 19 introduced Actions and useOptimistic, I rebuilt a form in my practice app first, noted pitfalls, and then shared a short demo with my team before we adopted it.
14

What is the difference between props and state?

Save to ▾
Show answer
Props are inputs passed from a parent component and are read-only inside the child. State is data owned and managed by the component itself with useState or useReducer, and changing it triggers a re-render. A simple rule: if a value comes from outside and the component does not change it, it is a prop; if it changes over time due to user action or data loading, it is state.
15

Can a child component modify its props?

Save to ▾
Show answer
No. Props are read-only, and a component must behave like a pure function with respect to its props. Mutating a prop object would not trigger a re-render and would cause confusing bugs in the parent. If a child needs to change something, the parent should own that state and pass down a callback such as onChange, which the child calls with the new value.
16

What does lifting state up mean?

Save to ▾
Show answer
Lifting state up means moving shared state to the closest common parent of the components that need it. The parent holds the state and passes the value and a setter callback down as props. For example, a temperature input and a converter display both read from state kept in their parent. This keeps a single source of truth instead of two components trying to stay in sync.
17

What is prop drilling and how can you avoid it?

Save to ▾
Show answer
Prop drilling is passing props through several layers of components that do not use them, only to reach a deeply nested child. It makes code noisy and hard to refactor. Solutions include component composition (passing JSX as children so intermediate layers do not need the data), the Context API for app-wide values like theme or user, and state libraries such as Zustand or Redux Toolkit for complex shared state.
18

How do you update objects and arrays in state without mutating them?

Save to ▾
Show answer
Always create new copies so React detects the change by reference. // object setUser(u => ({ ...u, city: 'Pune' })); // add to array setItems(list => [...list, newItem]); // remove setItems(list => list.filter(i => i.id !== id)); // update one item setItems(list => list.map(i => i.id === id ? { ...i, done: true } : i));
19

How do you give default values to props in a function component?

Save to ▾
Show answer
Use JavaScript default parameters while destructuring props. defaultProps for function components was removed in React 19, so this is the standard way. function Button({ label = 'Submit', variant = 'primary', onClick }) { return ( <button className={`btn btn-${variant}`} onClick={onClick}> {label} </button> ); }
20

What is the children prop?

Save to ▾
Show answer
children is a special prop containing whatever JSX you place between a component's opening and closing tags. For example, in <Card><h3>Title</h3></Card>, the h3 is passed as props.children. It lets you build wrapper components like layouts, modals and cards that do not need to know their content in advance. It is the foundation of composition in React.
21

What is the difference between controlled and uncontrolled components?

Save to ▾
Show answer
In a controlled component, the form value lives in React state and the input gets value and onChange props, so React is the single source of truth. In an uncontrolled component the DOM keeps the value and you read it with a ref or FormData when needed. Controlled inputs make validation and conditional UI easy; uncontrolled inputs are simpler and can perform better for large forms.
22

How does a child component send data back to its parent?

Save to ▾
Show answer
The parent passes a callback function as a prop, and the child calls it with the data. function Parent() { const [city, setCity] = useState(''); return <CityPicker onSelect={setCity} />; } function CityPicker({ onSelect }) { return ( <select onChange={e => onSelect(e.target.value)}> <option>Delhi</option> <option>Noida</option> </select> ); }
23

A teammate writes user.name = 'Ravi' inside a click handler and the screen does not update. Why?

Save to ▾
Show answer
React decides to re-render when you call the state setter with a new value. Mutating the existing object does not call the setter, and even if you call setUser(user) with the same mutated object, React compares by reference with Object.is, sees no change and may skip rendering. Always create a new object, like setUser({ ...user, name: 'Ravi' }).
24

What are React hooks and what are the rules of hooks?

Save to ▾
Show answer
Hooks are functions like useState and useEffect that let function components use state, side effects, context and other React features. Two rules apply: call hooks only at the top level of a component or custom hook, never inside loops, conditions or nested functions, and call them only from React functions. React relies on the call order being the same on every render to match state to each hook.
25

How does the dependency array of useEffect control when the effect runs?

Save to ▾
Show answer
With no array, the effect runs after every render. With an empty array [], it runs once after the first mount (and twice in development StrictMode to test cleanup). With values like [userId], it runs after mount and again whenever any listed value changes, compared using Object.is. Every reactive value the effect reads, such as props and state, should be included in the array.
26

What is useRef used for?

Save to ▾
Show answer
useRef returns a mutable object { current } that persists across renders without causing a re-render when changed. It has two main uses: holding a reference to a DOM node, for example to focus an input, and storing mutable values like timer ids, previous values or flags that should not trigger rendering. Do not read or write ref.current during rendering, except for lazy initialisation.
27

What does useContext do?

Save to ▾
Show answer
useContext reads the current value of a context created with createContext. React finds the nearest matching Provider above the component and returns its value; if none exists, it returns the default value. Whenever the provider value changes, every component using that context re-renders. In React 19 you can render <ThemeContext value={theme}> directly instead of ThemeContext.Provider, and use(ThemeContext) also works.
28

You see the error 'Rendered more hooks than during the previous render'. What is wrong?

Save to ▾
Show answer
A hook is being called conditionally or after an early return, so the number of hooks changes between renders. For example, if (!user) return null; placed before a useState call. React matches hooks by call order, so this breaks. Move all hook calls to the top of the component before any condition or early return, and put the condition inside the hook logic instead.
29

What is the Context API and when should you use it?

Save to ▾
Show answer
Context lets a parent provide a value to any component below it without passing props through every level. You create it with createContext, provide a value high in the tree and read it with useContext. It is ideal for values that many components need and that change rarely, such as theme, language, logged-in user or feature flags. It is not a full replacement for a state management library.
30

Explain the core concepts of Redux.

Save to ▾
Show answer
Redux keeps global state in a single store. The UI dispatches actions, which are plain objects describing what happened, like { type: 'cart/added', payload }. Reducers are pure functions that take the current state and an action and return new state. Components read state with selectors. This strict one-way flow makes state changes predictable, traceable in DevTools and easy to test.
31

How do you set up a Redux store and use it in components?

Save to ▾
Show answer
Use configureStore, wrap the app with Provider and use hooks. const store = configureStore({ reducer: { counter: counterReducer } }); createRoot(el).render( <Provider store={store}><App /></Provider> ); function Counter() { const value = useSelector(state => state.counter.value); const dispatch = useDispatch(); return <button onClick={() => dispatch(increment())}>{value}</button>; }
32

Why must Redux reducers be pure functions?

Save to ▾
Show answer
A pure reducer returns new state based only on its inputs and has no side effects: no API calls, no random values, no mutation of arguments. This makes state changes predictable, testable and replayable, which is what enables time-travel debugging in Redux DevTools. Side effects belong in thunks, listeners or RTK Query. Redux Toolkit uses Immer, so draft mutations inside createSlice are still safe.
33

How do you debug Redux state changes?

Save to ▾
Show answer
Install the Redux DevTools browser extension; configureStore enables it automatically in development. You can see every dispatched action, the state before and after, the diff, and jump back in time to earlier states. Check whether the expected action was dispatched, whether its payload is correct and whether the reducer updated the right slice. For selectors, log their output or use the React DevTools profiler.
34

What is the Flux architecture?

Save to ▾
Show answer
Flux is the unidirectional data flow pattern that inspired Redux. Actions describe events, a dispatcher sends them to stores, stores update data and notify views, and views render and trigger new actions. Data never flows backward directly. Redux simplified Flux into a single store with pure reducers. Understanding Flux explains why React state management favours one-way flow over two-way binding.
35

What is client-side routing and how does React Router provide it?

Save to ▾
Show answer
In client-side routing, the browser loads one HTML page and JavaScript swaps components when the URL changes, without a full page reload. React Router uses the History API to listen to URL changes, matches the path against your route definitions and renders the matching component. Navigation feels instant, state can be kept between pages and only data needs to be fetched from the server.
36

Show a basic React Router setup with a home page, a product page and a 404 page.

Save to ▾
Show answer
In React Router v7 (library mode) you can use declarative routes. import { BrowserRouter, Routes, Route } from 'react-router'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="/products/:id" element={<Product />} /> <Route path="*" element={<NotFound />} /> </Routes> </BrowserRouter> ); } The * path catches any unmatched URL.
37

How do you read a dynamic URL parameter like a product id?

Save to ▾
Show answer
Define the segment with a colon and read it with useParams. // route: <Route path="/products/:id" element={<Product />} /> import { useParams } from 'react-router'; function Product() { const { id } = useParams(); const { data } = useQuery({ queryKey: ['product', id], queryFn: () => getProduct(id) }); return <h1>{data?.name}</h1>; } Params are always strings, so convert with Number(id) if needed.
38

How do you navigate programmatically after a form submits?

Save to ▾
Show answer
Use the useNavigate hook. import { useNavigate } from 'react-router'; function CheckoutForm() { const navigate = useNavigate(); async function handleSubmit(e) { e.preventDefault(); const order = await placeOrder(); navigate(`/orders/${order.id}`, { replace: true }); } return <form onSubmit={handleSubmit}>...</form>; } replace: true stops the user from going back to the submitted form; navigate(-1) goes back.
39

Why use Link instead of a normal anchor tag in a React app?

Save to ▾
Show answer
A normal <a href> causes a full page reload, which throws away all React state and re-downloads the app. <Link to="/cart"> intercepts the click, updates the URL with the History API and lets the router render the new route instantly. It still renders a real anchor, so accessibility, middle-click and right-click open in new tab work. NavLink adds active styling for menus.
40

How do you read and update query parameters like ?page=2&sort=price?

Save to ▾
Show answer
Use useSearchParams, which works like useState for the query string. import { useSearchParams } from 'react-router'; function ProductList() { const [params, setParams] = useSearchParams(); const page = Number(params.get('page') ?? 1); const sort = params.get('sort') ?? 'popular'; const next = () => setParams({ page: String(page + 1), sort }); return <Pagination page={page} onNext={next} />; } Keeping filters in the URL makes them shareable and bookmarkable.
41

What is the difference between BrowserRouter and HashRouter?

Save to ▾
Show answer
BrowserRouter uses clean URLs like /products/5 with the HTML5 History API, but the server must be configured to serve index.html for every route. HashRouter puts the route after a hash, like /#/products/5; the server never sees the hash part, so it works on any static host without configuration. BrowserRouter is preferred for SEO and clean URLs; HashRouter suits simple static hosting or embedded apps.
42

How do you handle a form with multiple controlled inputs using one change handler?

Save to ▾
Show answer
Use the input's name attribute to update the right field. function SignupForm() { const [form, setForm] = useState({ name: '', email: '', city: '' }); const handleChange = e => { const { name, value } = e.target; setForm(f => ({ ...f, [name]: value })); }; const handleSubmit = e => { e.preventDefault(); console.log(form); }; return ( <form onSubmit={handleSubmit}> <input name="name" value={form.name} onChange={handleChange} /> <input name="email" value={form.email} onChange={handleChange} /> <button>Submit</button> </form> ); }
43

What are the common approaches to form validation in React?

Save to ▾
Show answer
You can validate manually in onChange or onSubmit and store errors in state, use HTML attributes like required and pattern for basic checks, or use a form library such as React Hook Form with a schema library like Zod or Yup. Schema validation keeps rules in one place and can be shared with the backend in TypeScript. Always validate again on the server, because client checks can be bypassed.
44

What does React.memo do?

Save to ▾
Show answer
React.memo wraps a component so React skips re-rendering it when its props are shallowly equal to the previous props. It is useful for components that render often with the same props and are expensive to render, like rows in a big table. It only works if props stay referentially stable, so objects and callbacks passed to it are usually memoised with useMemo and useCallback.
45

How do you implement code splitting with React.lazy and Suspense?

Save to ▾
Show answer
Load a component only when it is needed with a dynamic import. import { lazy, Suspense } from 'react'; const Reports = lazy(() => import('./Reports')); function App() { return ( <Suspense fallback={<Spinner />}> {showReports && <Reports />} </Suspense> ); } The bundler creates a separate chunk for Reports, reducing the initial JavaScript download.
46

How do you optimise images in a React app?

Save to ▾
Show answer
Serve modern formats like WebP or AVIF, resize images to their display size and use srcset with sizes for responsive images. Add loading="lazy" for images below the fold and fetchpriority="high" for the main hero image. Always set width and height or aspect-ratio to prevent layout shift. In Next.js, the next/image component automates resizing, formats and lazy loading.
47

A developer says the app is too slow, based on testing it with the development server. What do you tell them?

Save to ▾
Show answer
The development build includes extra warnings, StrictMode double rendering, checks and unminified code, so it is much slower and can mislead you. Production builds created with npm run build are minified, tree-shaken and optimised. Test performance on the production build, ideally on a mid-range Android phone with throttled network, because many Indian users browse on such devices and slower connections.
48

Tell me about a mistake you made that reached production and what you learned.

Save to ▾
Show answer
Situation: I removed what looked like an unused prop in a shared Button component. Task: after release, the payment page's disabled state broke. Action: I owned it immediately, rolled back, then fixed it and added a test plus a TypeScript type so the prop could not be removed silently. Result: the issue was live for under an hour, and I now search all usages and rely on types before deleting code.
49

What kinds of tests are written for a React application?

Save to ▾
Show answer
Unit tests check small pieces like utility functions, reducers and custom hooks. Component or integration tests render components with their children and check behaviour the user sees, usually with React Testing Library and Vitest or Jest. End-to-end tests run the full app in a real browser with Playwright or Cypress, covering flows like login and checkout. Static checks with TypeScript and ESLint catch many bugs before tests run.
50

What is the guiding philosophy of React Testing Library?

Save to ▾
Show answer
React Testing Library encourages testing components the way users use them, not their internal implementation. You find elements by role, label or text, interact with them through user events and assert what appears on screen. You avoid checking state variables or component instances. Its motto is that the more your tests resemble the way your software is used, the more confidence they give you, and refactors do not break them.
51

Jest or Vitest: what is the difference for React projects?

Save to ▾
Show answer
Both are test runners with a similar API (describe, it, expect, mocks). Jest is the long-established choice and still common in older projects. Vitest is built on Vite, reuses the same config and transforms, supports ESM and TypeScript natively and is much faster in watch mode, so it is the default for new Vite-based React apps. React Testing Library works with either.
52

Write a test for a counter component that increments on click.

Save to ▾
Show answer
Use React Testing Library with user-event. import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Counter from './Counter'; test('increments count', async () => { const user = userEvent.setup(); render(<Counter />); await user.click(screen.getByRole('button', { name: '+' })); expect(screen.getByRole('heading')).toHaveTextContent('1'); }); toHaveTextContent comes from @testing-library/jest-dom.
53

What is the difference between getBy, queryBy and findBy queries?

Save to ▾
Show answer
getBy returns the element or throws immediately if it is missing, so use it when the element should exist. queryBy returns null instead of throwing, which is the right choice to assert something is not present: expect(screen.queryByText('Error')).not.toBeInTheDocument(). findBy returns a promise and retries until the element appears or times out, used for content that appears after async work. Each has an AllBy variant for multiple elements.
54

How do you use React DevTools for debugging?

Save to ▾
Show answer
The Components tab shows the component tree; selecting one shows its props, state, hooks and context values, which you can edit live to test behaviour. You can find which component rendered a DOM node, view the owner chain and jump to source. The Profiler tab records renders and shows why each component re-rendered. Combined with browser breakpoints and console logs, it speeds up most UI debugging.
55

How do you respond when a senior developer leaves many comments on your pull request?

Save to ▾
Show answer
Situation: my first big PR received over twenty review comments. Task: address them and learn, not feel defensive. Action: I thanked the reviewer, fixed clear issues, asked questions on ones I did not understand and explained my reasoning politely on two where I had context. Result: the PR merged after one more round, and I created a personal checklist that reduced comments on later PRs.
56

A QA engineer raises a bug you believe is not a bug. How do you handle it?

Save to ▾
Show answer
Situation: QA reported that a filter reset on page refresh. Task: resolve it without friction. Action: I reproduced it, checked the acceptance criteria with QA and the product owner, and found the requirement was unclear rather than either of us being wrong. Result: we agreed to store filters in the URL, I implemented it in a day, and we added clearer criteria to future stories.
57

What is Next.js and why would you use it instead of plain React?

Save to ▾
Show answer
Next.js is a React framework that adds file-based routing, server-side rendering, static generation, React Server Components, API endpoints, image and font optimisation and production build tooling. Plain React with Vite is a client-side library setup where you choose routing and data fetching yourself. Next.js is preferred when you need SEO, fast first load, server logic close to the UI or a full-stack app in one codebase.
58

What are the special files in the Next.js App Router?

Save to ▾
Show answer
Inside the app folder, each route segment can have page.tsx (the UI for that URL), layout.tsx (shared UI that persists across child routes), loading.tsx (Suspense fallback shown while the page loads), error.tsx (error boundary, must be a Client Component), not-found.tsx (404 UI) and route.ts (API route handler). Folders in square brackets like [slug] create dynamic segments, and folders in parentheses group routes without affecting the URL.
59

How do environment variables work in a React or Next.js app?

Save to ▾
Show answer
Values are read at build time from .env files. In Next.js, only variables prefixed with NEXT_PUBLIC_ are exposed to the browser; others stay on the server. In Vite, the prefix is VITE_ and you read import.meta.env.VITE_API_URL. Anything sent to the browser is public, so never put secrets like database passwords or private API keys in client-exposed variables. Keep .env files out of Git.
60

Why do you want to work as a React developer?

Save to ▾
Show answer
I enjoy building things people use directly, and React lets me turn designs into fast, interactive screens. During my training I built three projects with React, TypeScript and APIs, and I liked how components make code reusable. React also has strong demand across startups and service companies in India, a large community and paths into Next.js and React Native, so I see long-term growth in this role.

Frequently asked questions

Who should practise easy React JS questions?

Freshers and career switchers should start here, and experienced candidates should skim them the day before an interview.

How should I practise these?

Answer each question aloud before opening the answer, mark it as solved only when your answer matches the key idea, and save misses to Last-Minute Revision.

Other difficulty levels