Chapter 5: Add React to an Existing Project
Core Idea
React doesn't require a rewrite — you can render interactive React components inside specific elements of an existing server-rendered or non-React page, or claim an entire subroute of an existing site for React.
Key Concepts
- Subroute integration: build the React part as a framework app, set its base path (
/some-app) in the framework config, and proxy /some-app/* requests to it. Lets that slice benefit from framework SSR/SSG/RSC without touching the rest of the site.
- Partial-page integration: set up a modular JS environment (Vite is the recommended zero-config path; Babel-transform an existing bundler setup if
<div /> already parses) then mount React only where you need it.
createRoot + getElementById: the core primitive for partial mounting — find an existing DOM node by id and render a component tree into it, leaving the rest of the server-rendered HTML untouched.
- React Native into an existing native app: same incremental philosophy applies mobile-side — add a React Native screen to an existing Android/iOS app rather than rewriting it.
- Migration pattern: start with small interactive islands (a button, a nav bar), then keep "moving upward" — if you eventually React-ify the whole page, migrate to a full framework at that point.
Code Examples
import { createRoot } from 'react-dom/client';
function NavigationBar() {
return <h1>Hello from React!</h1>;
}
const domNode = document.getElementById('navigation');
const root = createRoot(domNode);
root.render(<NavigationBar />);
- What it demonstrates: mounting a React component into one specific existing DOM node (
#navigation) without disturbing the rest of the HTML page around it.
Key Takeaways
- Partial adoption is a first-class, supported path — you don't need a green-field project to use React.
createRoot(domNode).render(<Component />) targeting an existing element id is the mechanical core of every partial-integration approach.
- If your existing bundler already accepts JSX syntax without erroring, reuse it; only reach for Vite/Babel setup when it doesn't.
Connects To
- Ch 94 (createRoot): the API reference for the primitive used here.
- Ch 4 (Installation): the decision tree that routes here vs. a full framework.