Client side routing, BrowserRouter versus HashRouter, useParams, useNavigate, nested routes, protected routes and data loaders.
11 questions6 fresher, 4 mid-level, 1 senior
React has no built-in router, so every real app makes a routing decision, and interviewers use it to check that you understand what a single page app actually does to the browser. The question behind the question is usually: do you know that the URL is state, and that treating it as state solves problems you would otherwise solve badly.
1.What is React Router and why does React need a routing library?
Fresher
React renders components; it has no concept of a URL. React Router maps URLs to components and keeps the address bar, history and back button in sync while the page is never actually reloaded.
It uses the History API to change the URL without a request, then renders the matching route. Frameworks such as Next.js and Remix ship their own routers built on the same idea, usually driven by the file system instead of a component tree.
2.What is the difference between client side routing and server side routing?
Mid-level
Server routing asks the server for a new HTML document on every navigation. Client routing intercepts the click, changes the URL with the History API and swaps components in place, so no document is fetched.
Server routing
Client routing
Navigation cost
A full document request and parse
A component swap, and maybe a data fetch
First load
Fast: HTML arrives ready
Slower: the bundle must load first
State
Lost on every navigation
Preserved across navigations
Needs
Nothing special
A server rewrite so deep links return the app shell
Likely follow-up questions
Why does refreshing a deep link 404 on a static host?
What does hybrid routing look like in Next.js?
3.What is the difference between BrowserRouter and HashRouter?
Fresher
BrowserRouter uses clean URLs through the History API and needs the server to serve the app for every path. HashRouter puts the route after a #, which the server never sees, so it works on any static host with no configuration.
BrowserRouter: /products/42. Clean, crawlable, requires a server rewrite.
HashRouter: /#/products/42. Works anywhere, but the fragment is never sent to the server, so no server rendering and weaker SEO.
MemoryRouter keeps history in memory with no URL at all, which is what you use in tests and in React Native.
Use BrowserRouter unless you are deploying somewhere you cannot configure, such as a legacy static host or a page embedded in another application.
Likely follow-up questions
Which one would you use inside an Electron app?
4.What is the difference between Link and a plain anchor tag?
Fresher
An anchor triggers a full page load, throwing away the app's state and re-downloading everything. Link renders an anchor but intercepts the click and navigates through the router instead.
<a href='/about'>About</a> // full reload
<Link to='/about'>About</Link> // client navigation
<NavLink to='/about'>About</NavLink> // adds an active state
Likely follow-up questions
Why is it important that Link renders a real anchor?
Params are always strings, so convert and validate them. Keeping filters and pagination in the query string rather than in component state is the point worth making: it makes the view shareable, makes the back button correct, and survives a refresh for free.
7.What are nested routes, and what does Outlet do?
Mid-level
Nested routes let a parent route render shared layout and a child route render inside it. Outlet is the placeholder in the parent where React Router renders whichever child matched.
<Route path='/settings' element={<SettingsLayout />}>
<Route index element={<Profile />} />
<Route path='billing' element={<Billing />} />
</Route>
function SettingsLayout() {
return (
<div className='settings'>
<SettingsNav />
<Outlet /> {/* Profile or Billing renders here */}
</div>
);
}
The layout component stays mounted as you move between children, so its state, scroll position and any data it loaded survive the navigation. index marks the child shown at the parent's own path.
Wrap the routes in a component that checks authentication and either renders an Outlet or redirects to the login page, remembering where the user was trying to go.
Wrap each route's component in React.lazy with a dynamic import and put a Suspense boundary above the routes, so each route's code downloads only when the user first visits it.
React Router's data routers can also declare a lazy route, which loads the component and its loader together. Either way, prefetch on hover or on link visibility if the navigation feels slow: the chunk is then usually already in cache by the time the user clicks.
10.What are loaders and actions in React Router's data APIs?
Senior
A loader is a function attached to a route that fetches its data before the route renders; an action handles form submissions to that route. They move data fetching out of components and remove the render-then-fetch waterfall.
Data fetching starts as soon as the navigation starts, in parallel with loading the route's code, instead of after the component mounts.
Nested route loaders run in parallel, so a layout and its child do not fetch one after the other.
errorElement gives each route its own error boundary, including for loader failures.
This is the same model Remix and the Next.js app router use, which is why it is worth knowing by name.
Likely follow-up questions
What is a fetch waterfall?
How does this compare to fetching in useEffect?
11.How do you handle a 404 and redirects?
Fresher
Add a catch-all route with path="*" for unmatched URLs, and render <Navigate to="..." replace /> for redirects. Order matters less in modern React Router because it ranks routes by specificity rather than by declaration order.