iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
You can create React-like behavior in a single HTML file with plain JavaScript: keep the current data in a state variable, respond to events, and update the page from that state. This gives you a clear state-to-view update loop without installing React or setting up a build tool.
Build a simple state-to-view loop with plain JavaScript
For a small interaction, treat the displayed page as a result of current state. A render function reads that state and updates the relevant DOM. Event handlers change the state, then call render again.
Save the following as an HTML file and open it in a browser. The script sits after the elements it uses, so they are already in the document when the script runs.
Free tools Windows power users keep installed
One-click scans. No signup required.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A state-driven counter</title>
</head>
<body>
<main>
<p>Count: <span id="count"></span></p>
<button id="decrease" type="button">Decrease</button>
<button id="increase" type="button">Increase</button>
</main>
<script>
const state = { count: 0 };
const countElement = document.querySelector("#count");
function render() {
countElement.textContent = state.count;
}
document.querySelector("#decrease").addEventListener("click", () => {
state.count -= 1;
render();
});
document.querySelector("#increase").addEventListener("click", () => {
state.count += 1;
render();
});
render();
</script>
</body>
</html>
The counter is the state; the event listeners are the actions; and render() updates the view. Calling it once at startup ensures the page reflects the initial state. This is a useful organization pattern built from browser APIs, not a special feature of HTML or JavaScript.
#1 Best Overall
Use event listeners and text updates
addEventListener() keeps behavior in JavaScript instead of scattering inline onclick attributes through the markup. MDN recommends this approach over inline event handlers, which couple behavior to the HTML. For plain text, use textContent rather than constructing an HTML string. See MDN’s guides to JavaScript and DOM events.
Choose between rendering state and updating one element
There are two reasonable ways to keep a small interaction in sync:
Rank #2
- Render from state: Change the state and call one render function. This is easier to follow as the number of displayed values grows, because the render function is the place that maps state to the page.
- Update a target directly: For a tiny interaction that changes only one value, update that element in the event handler. This avoids a separate render function, but separate handlers can become difficult to reason about if they all manipulate the same parts of the page.
This is an organizational choice, not a performance ranking. Browser APIs let you select elements, listen for events, create elements, and change their content; the right amount of structure depends on how much UI you are managing.
Know when the small pattern stops being enough
A state variable and render function work well for a counter, visibility toggle, or similarly bounded interaction. As an interface gains many related regions, components, or shared state, keeping every update coordinated by hand can become harder to maintain. React provides a component model for that kind of UI, but you do not need to adopt it just to make one element respond to a click.
For a small prototype or one-off tool, plain JavaScript keeps the file dependency-free and makes the browser mechanisms visible. For a widget that belongs in a React codebase, or an interface that benefits from reusable components and React-managed state, mounting React may be a better fit.
Mount React in one part of an existing HTML page
React can manage a specific region of a page rather than requiring the whole page to be rewritten. Add an element as a mount point, then create a root for that element. The essential client-rendering shape is:
Rank #4
import { createRoot } from 'react-dom/client';
const container = document.querySelector('#widget-root');
const root = createRoot(container);
root.render(<Widget />);
This illustrates the React API, but the example is not a complete standalone HTML file: the import and JSX need an environment that can resolve modules and compile JSX. React’s documentation describes adding React to an existing project, including the usual JavaScript tooling context. Its createRoot reference also documents multiple roots for pages where separate regions are managed by React.
Recommended Free Tools
What a single file does—and does not—mean
An HTML document can contain inline JavaScript and run without a build step. It is not automatically offline or dependency-free if it loads React, React DOM, Babel, or other scripts from external URLs: those resources still have to load. Babel Standalone can compile JSX in the browser for demonstrations, but it adds an external dependency and is better understood as a teaching or experimental setup than a default production workflow. See Babel Standalone documentation.
Best Value
External JavaScript modules can also behave differently when a page is opened directly with a file:// URL. MDN documents cross-origin loading issues in that situation and recommends testing with a local server. The inline vanilla example avoids modules and external requests.
Use the right React root for the starting markup
createRoot is for client-rendering React into a DOM node. If that node already contains HTML rendered by React on a server, use hydrateRoot instead; hydration attaches React behavior to that existing React-generated markup. They are not interchangeable. See React’s references for createRoot and hydrateRoot.
A blank client root remains blank until JavaScript loads and renders. If meaningful initial content matters before JavaScript runs, preserve useful HTML or generate the content ahead of time rather than relying on an empty mount point.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPick an approach based on the job
- One interaction, no dependencies: Use plain JavaScript in the HTML file. Keep state explicit and use a render function when it clarifies how the display follows that state.
- A small change to one value: A direct DOM update may be the simplest choice, provided the update logic remains easy to trace.
- A React widget within an existing page: Mount React into a designated element and use the project’s JavaScript environment for imports and JSX.
- A new full React application: React’s installation guidance accessed October 7, 2026 recommends starting with a framework. It still documents building from scratch for learning or constraints that do not fit a framework. Check the current React installation guidance when choosing a setup.
These choices are about dependencies, project structure, and the scope of the interface—not a claim that one option is faster. The documentation cited here does not provide a comparative performance benchmark for this example. React’s 19.3 release page is dated September 9, 2026.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

