Frontend Dev – What to Learn in a Framework

August 9, 20267 min readUpdated 8/20/2026

Frameworks are large and you will use a small part of each one every day. The trick to learning one quickly — and to switching later without starting over — is to know which questions every framework has to answer, and then go and find that framework's answer.

This post is that checklist. The examples are React, and the app behind them talks to a Spring Boot API, but the ten headings below are the same in Vue, Svelte and Angular. Learn them once and picking up the next framework is a week, not a year.

1. The language first

Every hour spent on the language pays off in every framework; every hour spent on framework trivia pays off in one. Before the framework, be comfortable with data types, objects and arrays, functions and closures, immutable updates, promises and async/await, modules, and enough TypeScript to describe an API response.

That is exactly the list in post 4. People who skip it spend months believing React is confusing when what is confusing is JavaScript.

2. Components and props

The unit of every modern frontend is a component: a function that takes data and returns markup. Props are its inputs, and they flow one way — parent to child, never back up.

interface Props {
  product: Product;
  onSelect: (product: Product) => void;
}

Note that the second prop is a function. That is how a child communicates upward: it does not reach into its parent, it calls the callback it was handed. Data down, events up. Learn that pattern and most component design follows.

3. The render model

This is the one that separates people who can debug from people who guess. For any framework, answer three questions:

  • What triggers a re-render? In React, a state or context change — not a mutated object.
  • What gets re-rendered? The component and everything under it, by default.
  • How does it decide what to actually touch in the DOM? A diff against the previous output. Which is why lists need stable keys — without them the framework cannot tell "inserted at the top" from "everything changed".

The consequence people trip on: a parent re-rendering re-renders its children even when their props are identical. The demo app hits this on a 14-card menu, and documents the fix:

export const ProductCard = memo(function ProductCard({ product, onSelect }: Props) {

with the reasoning next to it —

memo skips re-rendering a component when its props are unchanged (compared shallowly). It matters here because the menu renders 14 of these. Without memo, opening the cart drawer — which changes state in a PARENT — would re-render all 14 cards even though not one of their props changed.

And the catch that makes it a real skill rather than a magic word: memo only works if the props are referentially stable. An inline arrow function is a brand-new object every render, so the comparison never matches and the optimisation silently does nothing. That is why the parent wraps the callback in useCallback.

Do not sprinkle this everywhere. It costs a comparison on every render and only pays for components that are numerous, expensive, or both. More.

4. State and lifecycle

State is what the component remembers between renders. Lifecycle is how you run something at mount, on change, and at teardown.

The rule almost nobody is told early enough: most effects should not exist. If a value can be computed from existing state during render, compute it — do not mirror it into another piece of state and sync it with an effect. Effects are for stepping outside the framework: network calls, subscriptions, timers, focus.

When you do write one, two details are easy to get wrong, and the demo app calls both out:

useEffect(() => {
  const controller = new AbortController();

  async function load() {
    setLoading(true);
    setError(null);

1. AbortController + the cleanup function. In React 18+ StrictMode every effect runs twice in development; without cleanup you get two in-flight requests and the slower one can win, overwriting fresher state. Aborting on unmount also prevents setting state on a component that is no longer mounted. 2. Promise.all rather than three sequential awaits — the three requests are independent, so serialising them would triple the wait for no reason.

Cleanup is the half beginners skip, and it is where the intermittent bugs live. More.

5. Composition over configuration

Every framework gives you a way to pass markup into a component rather than a pile of boolean flags. In React it is children; elsewhere it is slots. The instinct to build is:

export function ProtectedRoute({
  children,
  requireAdmin = false,
}: {
  children: ReactNode;
  requireAdmin?: boolean;
}) {

A wrapper that takes whatever it is given, adds one behaviour, and gets out of the way. The alternative — a component with fifteen props controlling variations — is the thing you will be unpicking a year later.

6. Shared state

Sooner or later two components far apart need the same value and passing it through six layers of props stops being reasonable. Every framework has an answer — context, provide/inject, stores — and there is usually a heavier third-party option as well.

Learn where the threshold is rather than picking a side. Post 6 is entirely about this, including a real app that uses context on one half and Redux on the other, and the documented reason the line runs where it does.

7. Routing

What maps a URL to a screen, how you nest layouts, how you read a path parameter, and how you guard a route. Also: how you navigate without a full page load, and how you preserve "where were they trying to go" across a login redirect. Post 8.

8. Talking to an API

How requests are made, where that code lives, how errors surface, and how you avoid every component inventing its own fetch. Build one API layer, not forty call sites. Post 7.

Also learn how to mock it. Being blocked because the endpoint does not exist yet is a choice; a mock layer means frontend and backend can be built in parallel — which is exactly the workflow the two tracks on this site describe.

9. Forms and validation

Controlled inputs, submission, and showing an error next to the field it belongs to — including one that came back from the server. Forms are where most users actually touch your app and where the most careless code usually is. Post 8.

10. Testing

How to render a component in a test, how to simulate a click, how to assert on what a user would see, and how to run the whole thing in a real browser. Post 11.

The project-level questions

Separately from the framework's API, every framework makes you answer four questions about the project itself. These are quick, and being vague about them is what makes a codebase unpleasant.

QuestionWhat to find out
How do I create a project?The official starter and what it generates. For React that is Vite: npm create vite@latest.
How do I add a dependency?npm install, and the difference between dependencies and devDependencies — the second does not ship to users.
How do I configure per environment?So the same build runs against local, dev and prod. In Vite, import.meta.env and .env files — and nothing secret in them, see post 12.
How should I structure the code?Group by feature, not by file type, once the app is past a dozen screens.

On the third one, the demo app has exactly one line that decides where the backend is, with a local default so a fresh clone runs:

const BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8085';

The optional extras

Add these as you meet them. Some are one-time setup, some belong to a platform team, and at a small company all of them may land on you:

TopicWhen it becomes yours
CachingWhen the same data is fetched repeatedly. Usually a data library (TanStack Query) rather than something you build.
InternationalisationThe moment a second language is mentioned. Retrofitting it is genuinely expensive — ask early.
Error reportingAs soon as real users exist. You cannot fix what you never hear about.
AnalyticsWhen somebody asks whether the feature is used.
Feature flagsWhen you want to merge before you launch.
Server-side renderingWhen SEO or first-paint on slow devices matters. This is the Next.js/Nuxt/SvelteKit conversation.
Design systemWhen two teams keep building slightly different buttons.

How to learn one in a week

  1. Scaffold the starter project and read every file it generated until none is a mystery.
  2. Build one screen that lists something from a real API — that is components, state, effects and fetching at once.
  3. Add a second route and navigate between them.
  4. Add a form that posts back, with a loading state and an error state.
  5. Add a guarded route and a login.
  6. Write one end-to-end test that walks all of it.

Those six steps touch every heading above. Finish them and you can work in the framework; the rest is depth you can acquire while being paid.

The one thing to take from this post

Frameworks differ in syntax and agree on questions. Components, rendering, state, lifecycle, sharing, routing, data, forms, testing, configuration — ten headings, and every framework's documentation has a page for each. Learn the questions and you are not learning React, you are learning frontend.

Next: State Management.