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
| Kind | Example | Where it lives |
|---|---|---|
| Local UI state | modal open, input text | useState in the component |
| Shared UI state | theme, sidebar open | Context or a small store (Zustand) |
| Server state | users, products, orders | A data-fetching cache (TanStack Query, SWR) or server components |
| URL state | current page, filters, search | The URL (?page=2&q=react) |
| Form state | fields, validation errors | Local 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:
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:
<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
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, formattersGroup by feature, not by file type, once an app grows.
Error handling
- Error boundaries (a class component with
componentDidCatch, or thereact-error-boundarypackage) 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.
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.