Full stack development: MERN

Sefism.

Chapter 02

Git, npm and React

Version control and packages, then React: components, state, effects, forms and routing for the interface your backend serves.

Git branches and pull requests

Also called PR, merge, rebase, pull request

What
A branch is a cheap pointer to a line of commits. You work on a branch, push it and open a pull request, where CI runs and teammates review before merging into main.
Why
Keeps main deployable and gives every change a reviewed, reversible history.
Shell
git switch -c feat/comments
git add -p
git commit -m "Add comments to post page"
git push -u origin feat/comments

Watch out

Committing .env files or secrets; once pushed, rotate the secret, because deleting the file does not remove it from history.

npm, package.json and lockfiles

Also called semver, npm ci, npm, lockfile

What
package.json lists dependencies and scripts; package-lock.json pins exact versions of the whole tree. Versions follow semver (MAJOR.MINOR.PATCH), and ^ allows minor and patch updates.
Why
Commit the lockfile and use npm ci in CI and Docker so every environment installs the same code.

Watch out

Installing a package for one small helper without checking its size, maintenance and security history.

Components and props

Also called JSX

What
A React component is a function that returns JSX. Props are its read only inputs, passed down from the parent, including children.
Why
Components break a UI into testable pieces, and one way data flow makes it clear where each value comes from.

Watch out

Defining a component inside another component, which remounts it and loses its state on every render.

State and useState

Also called useState, React state

What
useState gives a component a value that survives re-renders and a setter that triggers one. State is replaced, never mutated, and anything derivable from it is calculated during render.
Why
State lives in the lowest component that needs it, lifted up only when siblings share it. Server data belongs in a data layer, not copied into state.
TSX
const [todos, setTodos] = useState<Todo[]>([]);

function toggle(id: string) {
  setTodos((prev) =>
    prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
  );
}

Watch out

Mutating an array in state with push, so React sees the same reference and does not re-render.

Effects and useEffect

Also called useEffect, dependency array

What
useEffect runs after render to synchronise with something outside React, such as a subscription, a timer or a browser API, and returns a cleanup function.
Why
Effects are an escape hatch. Event logic belongs in handlers and derived values in render; overusing effects is the most common React bug.

Watch out

Fetching in an effect with no cleanup, so a slow old response overwrites a newer one when inputs change quickly.

Forms and validation

Also called controlled inputs, zod

What
Inputs are controlled by state or read from FormData on submit. Validation runs in the browser for fast feedback and again on the server, often with one shared schema library such as Zod.
Why
Good forms show errors next to the field and keep what the user typed. Client validation is a convenience, never a security check.

Watch out

Trusting client side validation alone; anyone can send any request straight to your API.

Routing

Also called React Router, App Router

What
Mapping URLs to screens. Next.js uses folders in app/ with page.tsx and layout.tsx; a Vite React app uses React Router, declaring routes in code with nested layouts and URL params.
Why
Every screen with its own URL can be bookmarked, shared and reloaded, and layouts keep navigation shells in place.
JavaScript
<BrowserRouter>
  <Routes>
    <Route element={<AppLayout />}>
      <Route index element={<Home />} />
      <Route path="posts/:id" element={<PostPage />} />
      <Route path="*" element={<NotFound />} />
    </Route>
  </Routes>
</BrowserRouter>

// inside PostPage
const { id } = useParams();

Fetching API data in React

Also called TanStack Query, loading states

What
A Vite React app loads data from your API in the browser. A library such as TanStack Query handles caching, loading and error states, retries and refetching after a mutation.
Why
Hand written fetch effects miss race conditions, caching and invalidation. A data library turns each API call into a few lines.
TSX
const { data, isPending, error } = useQuery({
  queryKey: ['posts', page],
  queryFn: () =>
    fetch(`/api/posts?page=${page}`).then((r) => {
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      return r.json();
    }),
});

Vite dev server and API proxy

Also called Vite, VITE_ variables, Vite proxy

What
Vite serves the React app in development with instant reloads and builds static files for production. Its server.proxy option forwards /api calls to your backend on another port.
Why
The proxy makes frontend and API look like one origin in development, avoiding CORS setup until you deploy them separately.
TypeScript
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: { '/api': 'http://localhost:8000' },
  },
});

Watch out

Putting secrets in VITE_ variables: they are bundled into public JavaScript.

02 · Git, npm and React2 / 8