Utilrix

Online React Editor & Playground

Write React components in your browser with a live preview, then download the whole thing as a Vite project.

1:1
PREVIEW
Rendered in a sandboxed iframe in this tab. React and the JSX compiler are fetched once (about 3MB) and then cached — your own code is never uploaded.

React examples you can run

Every one of these is loaded from the Examples menu in the editor above — press Run and it works. They are printed here so you can read the code before you run it.

State & lists

useState with an updater function, useMemo for a derived count, a controlled input, and a keyed list.

import { useState, useMemo } from "react";

const TASKS = [
  { id: 1, title: "Learn hooks", done: true },
  { id: 2, title: "Build a list", done: false },
  { id: 3, title: "Ship it", done: false },
];

export default function App() {
  const [tasks, setTasks] = useState(TASKS);
  const [draft, setDraft] = useState("");

  const remaining = useMemo(() => tasks.filter((task) => !task.done).length, [tasks]);

  function toggle(id) {
    setTasks((current) =>
      current.map((task) => (task.id === id ? { ...task, done: !task.done } : task))
    );
  }

  function add(event) {
    event.preventDefault();
    if (!draft.trim()) return;
    setTasks((current) => [...current, { id: Date.now(), title: draft.trim(), done: false }]);
    setDraft("");
  }

  return (
    <main className="app">
      <h1>Tasks</h1>
      <p className="count">{remaining} left</p>

      <form onSubmit={add}>
        <input
          value={draft}
          onChange={(event) => setDraft(event.target.value)}
          placeholder="Add a task…"
        />
        <button type="submit">Add</button>
      </form>

      <ul>
        {tasks.map((task) => (
          <li key={task.id} className={task.done ? "done" : ""}>
            <label>
              <input type="checkbox" checked={task.done} onChange={() => toggle(task.id)} />
              {task.title}
            </label>
          </li>
        ))}
      </ul>
    </main>
  );
}

useEffect & timers

useEffect with an interval and — the part people miss — the cleanup function that clears it.

import { useEffect, useRef, useState } from "react";

export default function App() {
  const [seconds, setSeconds] = useState(0);
  const [running, setRunning] = useState(false);
  const laps = useRef([]);

  useEffect(() => {
    if (!running) return;
    const id = setInterval(() => setSeconds((value) => value + 1), 1000);
    // Cleanup runs when running flips or the component unmounts.
    return () => clearInterval(id);
  }, [running]);

  const minutes = String(Math.floor(seconds / 60)).padStart(2, "0");
  const remainder = String(seconds % 60).padStart(2, "0");

  return (
    <main className="app">
      <h1>{minutes}:{remainder}</h1>
      <div className="row">
        <button onClick={() => setRunning((value) => !value)}>
          {running ? "Pause" : "Start"}
        </button>
        <button onClick={() => { laps.current.push(seconds); setSeconds(0); }}>Lap</button>
        <button onClick={() => { setRunning(false); setSeconds(0); laps.current = []; }}>
          Reset
        </button>
      </div>
      <ul>
        {laps.current.map((lap, index) => (
          <li key={index}>Lap {index + 1}: {lap}s</li>
        ))}
      </ul>
    </main>
  );
}

Components & props

Components composed through props and children, with default values and the spread shorthand.

function Stat({ label, value, tone = "neutral" }) {
  return (
    <div className={"stat stat-" + tone}>
      <span className="stat-value">{value}</span>
      <span className="stat-label">{label}</span>
    </div>
  );
}

function Card({ title, children }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      {children}
    </section>
  );
}

export default function App() {
  const stats = [
    { label: "Users", value: "1,204", tone: "up" },
    { label: "Churn", value: "2.1%", tone: "down" },
    { label: "Revenue", value: "₹4.2L", tone: "up" },
  ];

  return (
    <main className="app">
      <Card title="This month">
        <div className="stats">
          {stats.map((stat) => (
            <Stat key={stat.label} {...stat} />
          ))}
        </div>
      </Card>
    </main>
  );
}

React quick reference

The syntax people look up most often. Copy any line into the editor above to see what it does.

Hooks

WhatSyntaxNotes
useStateconst [n, setN] = useState(0)Use setN(v => v + 1) when the next value depends on the last.
useEffectuseEffect(() => { ... }, [deps])Return a function to clean up; [] means run once.
useMemouseMemo(() => compute(a), [a])Caches a value between renders.
useCallbackuseCallback(fn, [deps])Caches a function so a child doesn't re-render.
useRefconst ref = useRef(null)A box that survives renders without causing one.
useReducerconst [state, dispatch] = useReducer(fn, init)For state with several related fields.
useContextconst value = useContext(Ctx)Reads the nearest provider.

JSX rules that trip people up

WhatSyntaxNotes
ClassclassName="card"class is a reserved word in JavaScript.
Lists need keysitems.map((i) => <li key={i.id}>A stable id, not the array index.
Conditional{ready && <Spinner />}Careful with 0 — it renders as 0.
Fragment<>...</>Group children without an extra element.
Inline stylestyle={{ color: 'red' }}An object, camelCased.
EventonClick={handleClick}Pass the function; don't call it.

State patterns

WhatSyntaxNotes
Update an objectsetUser({ ...user, name })Never mutate state in place.
Update in a listsetItems(list => list.map(i => i.id === id ? { ...i, done: true } : i))Replace the one, copy the rest.
RemovesetItems(list => list.filter(i => i.id !== id))filter returns a new array.
AddsetItems(list => [...list, item])Spread, don't push.
Lift state upkeep it in the closest common parentTwo siblings that need the same value.

Other languages you can run here

Processed 100% in your browser — nothing you enter here is ever uploaded.

Common use cases

Learning hooks

State, effects, refs and memoisation, each with a runnable example. Change a dependency array and watch the behaviour change.

Prototyping a component

Sketch a card, a form or a list in isolation, get it right, then paste it into your real project — or download the whole thing as a Vite app.

Sharing a reproduction

Reduce a bug to one component and send the link. No sandbox account, no waiting for a container to boot.

Interview and assignment practice

Build the classic exercises — todo list, counter, stopwatch, filtered table — and keep the ZIP as your submission.

How to use the React Playground

Write your component in App.jsx and style it in styles.css — the preview renders your app about half a second after you stop typing.

Export a component as the default export, or name a function App, and it is mounted for you. React 19 and the hooks you expect are already available; there is nothing to import or install.

console.log from inside your component appears in the console strip under the preview, and a render error shows its message there instead of a blank screen.

Suggestions include the hooks with their signatures — useState, useEffect, useMemo, useCallback, useRef — plus a component snippet. Ctrl + Space asks for them.

Press ZIP to download a complete Vite project: package.json, vite.config.js, index.html, main.jsx and your files. npm install, npm run dev, and you are working locally.

Share copies a link with your component encoded inside it, so a reviewer opens exactly what you wrote.

Frequently asked questions

Related tools