Key Takeaways
- React builds interfaces from reusable components that describe the UI for their current data.
- Props pass information into components; state lets components remember information between renders.
- JSX is optional, but widely used. It describes React elements rather than creating browser DOM nodes directly.
- React provides state APIs, but routing and broader application architecture come from surrounding tools or frameworks.
React, also called React.js or ReactJS, is a JavaScript library for building user interfaces from reusable components. You describe what the interface should display for the current data, and React coordinates updates when that data changes. Its central benefit is this declarative programming model—not a promise that every application will run faster.
What Is React.js?
A component is a reusable piece of an interface, such as a button, search box, or entire page. Components can display information, manage interactions, or do both; React doesn't require you to separate all presentation from all logic.
React core includes state APIs such as useState. It doesn't prescribe your application's routing or data-fetching architecture, so the practical distinction between a React library and a React framework is what the surrounding tools provide.
React Library vs. Framework: Choosing a Starting Point
React's documentation recommends starting new applications with a framework. Next.js and React Router framework mode provide application-level capabilities around React, including routing and server-rendering options; a client-only setup remains useful for learning and suitable applications.
| Approach | What It Provides | When to Consider It |
|---|---|---|
| A React framework | Integrated routing, data-loading conventions, and rendering strategies. | You want application-level decisions handled together. |
| React with Vite | A development server and build tooling; you choose additional application libraries. | You're learning React or deliberately building a client-side application. |
These aren't competing component models: both approaches use React components. The difference is how much infrastructure you assemble yourself.
React Introduction: Start a New Project
For this tutorial, use Vite's JavaScript React template. Install a supported Node.js release that meets the requirements in the Vite getting-started guide, then run these commands.
npm create vite@latest react-intro -- --template react
cd react-intro
npm install
npm run devOpen the local address printed in the terminal. For a longer setup walkthrough, follow our guide to creating a React app with Vite.
Build Your First React Components
This example connects three concepts: a component defines a reusable UI unit, props configure that component, and state holds information that can change. Props are read-only inputs supplied by a parent component; state is React-managed memory.
Add Components, Props, and State
Replace src/App.jsx with the following code. Both buttons display the same counter because their parent, App, owns the state.
import { useEffect, useState } from 'react';
function CounterButton({ label, count, onIncrement }) {
return (
<button type="button" onClick={onIncrement}>
{label}: {count}
</button>
);
}
export default function App() {
const [count, setCount] = useState(0);
useEffect(() => {
const previousTitle = document.title;
document.title = `Clicks: ${count}`;
return () => {
document.title = previousTitle;
};
}, [count]);
function handleIncrement() {
setCount(current => current + 1);
}
return (
<main className="counter">
<h1>React counter</h1>
<CounterButton
label="First button"
count={count}
onIncrement={handleIncrement}
/>
<CounterButton
label="Second button"
count={count}
onIncrement={handleIncrement}
/>
</main>
);
}Click either button: both displayed counts increase, and the browser tab title changes. Reusing CounterButton with different label props changes its text without duplicating its implementation.
Mount the Application with createRoot
Replace src/main.jsx with this entry point. The generated template's index.html already contains the root container.
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';
const container = document.getElementById('root');
if (!container) {
throw new Error('Missing #root container');
}
createRoot(container).render(
<StrictMode>
<App />
</StrictMode>
);createRoot, imported from react-dom/client, creates a React root inside a browser DOM element. Calling its render method displays the application; subsequent state changes don't require you to call it again. Frameworks commonly manage this entry point for you.
React.js Key Characteristics
The example brings together React's main ideas: reusable components, JSX, one-way data flow, and declarative rendering. Understanding how they connect matters more than memorizing terminology.
JSX Is Optional, and It Isn't HTML
JSX is a JavaScript syntax extension for describing markup. A build tool transforms it into JavaScript that creates React element descriptions; Vite supports JSX files. Those descriptions aren't browser DOM nodes.
- Use
classNamefor a CSS class, as inclassName="counter". - Put JavaScript expressions in braces, such as
{count}. - Capitalize your component names, such as
CounterButton; built-in tags such asbuttonare lowercase. - Close every tag and wrap adjacent JSX elements in a shared parent or Fragment.
You can build the same element descriptions without JSX using React's createElement API. JSX is optional, but its markup-like structure makes nested interfaces easier to scan. For more syntax examples, see our React JSX tutorial.
Unidirectional Data Flow Keeps Ownership Clear
In the example, App passes count, label, and an event-handler function down to each button as props. A button reports an interaction by calling that function; it doesn't mutate its parent's state. This is one-way data flow with an explicit path for interactions.
App owns count
|
+-- props: count, label, onIncrement --> CounterButton
|
+-- props: count, label, onIncrement --> CounterButton
Button click --> handler in App --> state update --> new propsMoving shared state to the closest common parent is called lifting state up. If each button instead declared its own useState, the buttons would have independent counters. Our React props and state guide develops this distinction further.
Hooks Add State and Synchronize External Systems
Hooks are React functions that let components use features such as state. Here, useState(0) returns the current count and its setter, setCount. The updater current => current + 1 calculates the next value from pending state; it doesn't change the current render's count variable.
useEffect synchronizes a component with something outside React's rendering logic. Here, it updates the document title, which controls the browser tab's title. The [count] dependency list makes React rerun the Effect after commits where count changes; cleanup restores the previous title before the next setup and when the component is removed. Effects don't run during server rendering.
You don't need an Effect to calculate values from existing props or state. Calculate those during rendering instead; use Effects for synchronization, not as the default way to coordinate application data.
The Virtual DOM: Rendering and Committing
“Virtual DOM” is shorthand for an in-memory UI representation, not a second browser DOM layered over the real one. Reconciliation is React's process of matching new UI descriptions with previous work to determine what needs updating.
For a browser application, distinguish these steps:
- Trigger: Initial mounting or a state update requests rendering work.
- Render: React calls components to calculate the UI for their current inputs.
- Commit: React applies the required changes to the browser DOM. Rendering doesn't necessarily produce a DOM change.
Interaction --> state update --> render components --> commit DOM changes
| |
calculate the UI update the pageReact can batch state updates, and it can skip work in some circumstances. Neither behavior means that every component render becomes cheaper or that reconciliation guarantees the globally smallest set of DOM operations. Treat React as a programming model first, and measure performance rather than assuming an automatic speed advantage.
React Rendering Isn't Limited to the Browser DOM
React applications can generate HTML on a server or during a build. Hydration connects React's client-side behavior to that existing HTML; the entry point is hydrateRoot, not createRoot. A framework normally coordinates this workflow.
React Native uses React's component model to build native interfaces rather than browser DOM elements. It's a separate rendering environment—not a promise that a web component using button or div will run unchanged on mobile.
When Do You Need Routing or a State Library?
Use routing when your interface needs URL-addressable screens and navigation behavior. A framework can supply this architecture, or you can add a router to a client-side setup.
For state, start with local state and lift it when components need to share it. React also provides context for passing information through a tree and useReducer for organizing update logic.
Redux is optional, not the mechanism that gives React one-way data flow. Consider an external store when substantial shared state, complex transitions, or debugging requirements justify another abstraction.
Common Mistakes
- Mutating props or existing state objects. Treat them as read-only; replace state objects and arrays rather than modifying them in place.
- Calling the handler while rendering. Pass
onClick={handleIncrement}, notonClick={handleIncrement()}. - Calling state and Effect Hooks conditionally. Call
useStateanduseEffectat the top level of a component or custom Hook, not inside loops or conditions. - Removing Strict Mode to hide duplicate development work. In this root-level setup, Strict Mode performs extra development-only rendering and Effect checks to expose impure code and missing cleanup. Fix the underlying issue instead.
FAQ
Is React a library or a framework?
React is a UI library with component and state APIs. Frameworks such as Next.js and React Router framework mode build on React to provide application-level routing, data loading, and rendering choices.
Do I need to use JSX with React?
No. You can create React elements with createElement instead, but JSX is widely used because it makes nested interface descriptions easier to read. JSX requires transformation into JavaScript before execution.
What are React components, props, and state?
Components are reusable pieces of an interface. Props are read-only inputs passed into a component, while state is component memory that can be updated to request another render.
Do I need Redux to manage state in React?
No. React includes built-in state APIs, and shared state can often be handled by lifting it to a common parent or using context. Redux is an optional tool for applications whose state-management needs justify it.
How should I start a new React application?
React recommends starting new applications with a framework. Vite is also an option for learning React or building a suitable client-side application; Create React App is deprecated.
Further Reading
- React Quick Start — components, events, and sharing data.
- Creating a React App — framework recommendations and starting from scratch.
- Vite Getting Started — prerequisites, templates, and development commands.
- Writing Markup with JSX — syntax rules and differences from HTML.
- useState Reference — state setters, updater functions, and common pitfalls.
- useEffect Reference — dependencies, synchronization, and cleanup.
- createRoot Reference — browser entry points and hydration caveats.
- Render and Commit — the difference between calculating UI and updating the DOM.
