← React, from components to interview-ready

Lesson 5 of 5

Architecture: state management, routing, data fetching and testing

4 min read

Interviews for freshers and juniors increasingly include "how would you structure this app?" Here's a practical mental model.

Kinds of state

KindExampleWhere it lives
Local UI statemodal open, input textuseState in the component
Shared UI statetheme, sidebar openContext or a small store (Zustand)
Server stateusers, products, ordersA data-fetching cache (TanStack Query, SWR) or server components
URL statecurrent page, filters, searchThe URL (?page=2&q=react)
Form statefields, validation errorsLocal state or React Hook Form

The most common mistake is putting server data into a global store and syncing it by hand. A server-cache library handles loading states, caching, background refresh and invalidation.

Redux Toolkit in 60 seconds

Redux keeps app state in one store, changed only by dispatching actions handled by pure reducers. Redux Toolkit removes the boilerplate:

js
const cartSlice = createSlice({
  name: "cart",
  initialState: { items: [] },
  reducers: {
    added(state, action) { state.items.push(action.payload); }, // Immer makes this safe
    removed(state, action) { state.items = state.items.filter((i) => i.id !== action.payload); },
  },
});
export const { added, removed } = cartSlice.actions;

// in a component
const items = useSelector((s) => s.cart.items);
const dispatch = useDispatch();
dispatch(added(product));

When to choose Redux: large apps, many developers, complex shared state, need for devtools time-travel and strict patterns. For smaller apps, Context + hooks or Zustand is enough.

Routing

With React Router:

jsx
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/jobs/:slug" element={<JobPage />} />
  <Route path="*" element={<NotFound />} />
</Routes>
// inside JobPage
const { slug } = useParams();
const navigate = useNavigate();

Frameworks like Next.js use file-based routing: app/jobs/[slug]/page.tsx is the /jobs/:slug page. Next.js also adds server components, server-side rendering and API routes. Know the difference between CSR (render in browser), SSR (render per request on the server), SSG (render at build time) and ISR (static, regenerated periodically).

Folder structure that scales

text
src/
  components/      shared, dumb UI (Button, Modal)
  features/
    cart/          CartPage.jsx, CartItem.jsx, cartSlice.js, api.js
    auth/
  hooks/           useDebounce.js, useLocalStorage.js
  lib/             api client, formatters

Group by feature, not by file type, once an app grows.

Error handling

  • Error boundaries (a class component with componentDidCatch, or the react-error-boundary package) catch render errors in a subtree and show a fallback instead of a white screen.
  • Async errors (fetch failures) are handled in your data layer and shown as UI states: loading, error with retry, empty, success.

Testing

  • Unit/component tests with Jest or Vitest + React Testing Library. Test what the user sees and does, not internal state.
jsx
test("adds a todo", async () => {
  render(<TodoApp />);
  await userEvent.type(screen.getByRole("textbox"), "Learn testing");
  await userEvent.click(screen.getByRole("button", { name: /add/i }));
  expect(screen.getByText("Learn testing")).toBeInTheDocument();
});
  • End-to-end tests with Playwright or Cypress for critical flows (signup, checkout).

Accessibility basics

Use real elements (button, not a clickable div), label every input, keep focus visible, manage focus when opening modals, and provide alt text. Interviewers notice when candidates mention it unprompted.

A take-home task checklist

Many companies (including on HireSol) hire through a short task. Before you submit:

  • It runs with one command and the README says how.
  • Loading, error and empty states are handled.
  • Components are small and named well; no dead code or console logs.
  • Forms validate input; the UI works at phone width.
  • A few meaningful tests, and a short note on trade-offs and what you'd do with more time.

Check yourself

  • Where should data fetched from an API live, and why not in Redux by default?
  • What is the difference between SSR and SSG?
  • What does an error boundary catch, and what does it not catch?

Sign up free to save your progress.

Architecture: state management, routing, data fetching and testing · React, from components to interview-ready · HireSol