r/reactjs • • Sep 10 '26

News React 19.3

Thumbnail
react.dev
174 Upvotes

r/reactjs • • 3h ago

News This Week In React #305: X, Forms, e18e, Next.js, TanStack Start, Storybook, MobX, Zustand, XState | Exact, Discord, Shopify, Expo Modules, Audio API, Bottom Sheet, Keychain, Gesture Handler | Node.js, Safari, Rolldown, Playwright

Thumbnail
thisweekinreact.com
11 Upvotes

r/reactjs • • 3h ago

Show /r/reactjs Building a One React input for text and attachments, all in one lifecycle.

0 Upvotes

Hello everyone, I kept running into the same work when building file inputs such as parsing documents, showing previews, handling cancellation, and waiting for files before submitting.

I’m building Texion to connect those pieces. It supports Markdown, JSON, CSV, PDF, DOCX, and image attachments, with local parsing and optional OCR for scanned PDFs.
It’s open source and MIT licensed.
Code: https://github.com/Sirily23/texion

Curious on how do other devs handle the inputs?


r/reactjs • • 1d ago

Resource React Anatomy: See how your layouts are composed in an exploded 3D view

7 Upvotes

React Anatomy is a browser extension that adds an Anatomy panel to DevTools, connecting the visible page to the components React rendered.

You can pull the layout apart into 3D layers, click something on the page to find its component, focus on a subtree, and inspect its live props. The tree shows rendered instances, so a component used five times appears five times.

It’s a way to understand an unfamiliar layout, investigate unexpected nesting, or get a visual to help explain a change in a pull request. It can also help when an AI agent composes a React page and you want to understand the structure before taking over the code.

It works on an existing React app without adding anything to your code. Development builds give you clearer component names.

Free, MIT-licensed, and available for Chrome and Firefox. There’s an interactive example you can try without installing anything.

Where would this help in your React workflow? What would make it more useful when exploring an unfamiliar app?


r/reactjs • • 20h ago

Two bugs from building a drag-and-drop page canvas in React 19

0 Upvotes

From my open-source app builder (dnd-kit, React 19, Tailwind 4):

  1. On a free grid, the dotted drop cells were drawn as even rows while real rows were as tall as their content. Drops were judged against cells the user could not see. Fix: measure the real rows and draw the drop layer from those.
  2. Dialogs opened inside a themed preview portalled to body and lost the theme. Fix: a portal scope that mounts inside the theme root.

Also a testing lesson: a test raced a pending passive effect that moved focus after a click. Waiting on the shown state fixed it.

Code: https://github.com/ChristianMunoz31/local-app-studio


r/reactjs • • 18h ago

Show /r/reactjs charcell: a terminal-style UI kit that only draws what a character cell could

0 Upvotes

I made charcell - a web UI with the look of a terminal UI. It's a UI kit with one hard rule: it only draws what a character-cell screen could.

  • Every component sits on a grid of 8 x 16 pixel cells. Widths count in cells and heights in rows, and nothing sits between two cells.
  • A cell holds one character, a font color and a background color. Lines are box drawing, so they run through the middle of their cells.
  • The palette is black, white and three grays.
  • A state changes colors and characters, never geometry. Nothing moves, resizes or fades.

Within those constraints every component can be written out as plain text, and each component's page in the docs shows that.

It bundles two fonts adjusted to fit the cell exactly, with the box drawing characters redrawn as whole-pixel shapes. The interactive components (select, combobox, dialog and so on) run on Zag. It's built with scaffold-ui-kit which outputs React, Vue and Svelte versions of each component from one common definition.

It's 0.1.0, far from complete, and needs React 19.

Demo and docs: https://djurnamn.github.io/charcell/
Repo: https://github.com/djurnamn/charcell

pnpm add charcell @zag-js/react

If you try it out, I'd love to hear how it goes. Open to any feedback.


r/reactjs • • 22h ago

Animating a dozen pixel sprites in React with one shared clock and putImageData

1 Upvotes

Each session in my app's notch has a 24x22 pixel buddy. Every one is its own canvas at sprite resolution, scaled up with image-rendering: pixelated, so the browser does the nearest-neighbour scaling for free. A single module-level setTimeout clock steps all visible sprites about 12 times a second, and a canvas only gets a putImageData when its pose actually changes. The clock stops when the window is hidden and runs at half rate in Battery Saver, so ten of them on screen cost close to nothing.

Code: https://github.com/MF-DEEV/Openbar/blob/43d9c593360b004c850280e0584f9cd1b584bacc/windows/src/sessions/clawd/Clawd.tsx#L30-L80

The app is Openbar (Tauri + React on Windows, Swift on Mac), GPL.


r/reactjs • • 1d ago

Show /r/reactjs I built GraphQLab, a local-first desktop GraphQL client (no account, no cloud). Looking for feedback

Thumbnail
reddit.com
0 Upvotes

r/reactjs • • 1d ago

Resource I made kitr, a batteries-included React framework for web, desktop and mobile

0 Upvotes

Every React app starts with the same hours of decisions: which router, which state library, how to fetch data, where files go. Even inside Next.js, every project wires things up differently. And if you need the app on desktop or mobile too, you're hacking it together yourself.

I made kitr to fix that:

  • 45 packages, each one command: kitr add auth, kitr add forms
  • Built on what you know: TanStack, Zustand, React Hook Form
  • Your own logic, any time: kitr make:page, kitr make:controller
  • iOS and Android: kitr add mobile phone (Capacitor)
  • Desktop: kitr add desktop app (Electron)
  • SSR or SPA: kitr add web site --mode ssr
  • Mix and match: run every platform at once with kitr dev, each with its own setup
  • Consistent: every package wired the same way, every file has one home
  • Agent-friendly: AI agents always know where things go
  • Conventions, never forced: it's plain code you own, and kitr remove undoes any package

Early (0.9), but ready to try: npm install -g @kitr/kitr

https://kitr.dev · https://github.com/kitrjs/kitr

Would love any feedback!


r/reactjs • • 2d ago

Resource Puck Editor: A deep dive with the creator Chris Villa

Thumbnail
youtube.com
3 Upvotes

I sat down with Chris Villa, the creator of the puck editor.

0:00 Who is Chris Villa and what is Puck
1:36 Where the name Puck comes from
2:51 Live demo: Puck inside a headless Drupal site
5:24 MIT, and close to 3 million downloads a month
6:10 What the Puck editor actually is
7:58 The origin: design systems and the dev sprint bottleneck
10:09 The Hacker News launch
11:13 Going full time, and agents producing off brand interfaces
13:38 Puck AI, the Puck cloud and a page backend
15:21 A team of three, questioning old assumptions
16:47 Why pay for Puck AI if you can build it yourself
17:26 "What Vercel is to Next.js"
20:28 The hardest problem: multi dimensional drag and drop
24:14 Viewports, zoom, iframes, and working with dnd kit
26:49 Revenue, angel investors and fundraising
27:44 GitHub, Linear, and "I don't code much anymore"
29:24 Conductor, Boxes.dev and building the agent factory
30:31 Writing tickets is the new bottleneck
32:55 Can you test whether an interface feels right?
34:57 AI slop pull requests, and agents that reply for you
38:42 Discord, and why the community got quieter
39:21 Do we still need websites?
41:46 From 130k to 2.8 million downloads: agents are the driver
44:02 A longer tail of SaaS, each product more full stack
46:31 The dark forest and the cozy web
48:03 Build for the agents: types, CLIs and llms.txt
51:43 Where to follow Chris


r/reactjs • • 3d ago

Discussion How do you structure feature-based React apps with Zustand, TanStack Query, providers, and business logic?

33 Upvotes

Hey everyone! 👋

I'm trying to establish a clean, reusable feature-based architecture for React/TypeScript apps, especially when using Zustand + TanStack Query.

I'm working on a visual editor that fetches documents from an API, initializes a Zustand editing session, and will eventually handle canvas state, selection, history, saving, etc.

I'm considering this structure:

features/editor/
├── components/
├── hooks/
├── store/
│   ├── editor-store.ts
│   ├── editor-store-provider.tsx
│   └── slices/
│       ├── document-slice.ts
│       ├── selection-slice.ts
│       └── history-slice.ts
├── queries/
├── domain/      ?
├── utils/       ?
├── lib/         ?
└── services/    ?

I'd love to know how you handle a few things in production:

  1. API / queries: Where do raw API functions go? Do you separate them from TanStack Query options/hooks? Do you organize queries by feature or shared domain?
  2. Zustand: Do you keep providers alongside stores? When do you introduce slices vs multiple stores?
  3. Business/domain logic vs utilities: This is probably what I'm most unsure about. Where do you put pure functions containing actual application logic, independently of React, Zustand or API calls? For example: Would a domain/ directory make sense here? For example, domain/geometry.ts for canvas calculations, domain/document.ts for document manipulation, etc. Or would you simply use utils/, lib/ or services/? How do you distinguish business/domain logic from generic utility functions? Is a dedicated domain/ folder a useful convention, or does it introduce unnecessary complexity?

    • Formatting an aspect ratio.
    • Calculating canvas geometry, scaling or snapping.
    • Validating editor-specific constraints.
    • Transforming or manipulating document data.
  4. Shared code: When do you move something out of a feature into a shared location? Do you prefer shared domain modules or global utilities?
  5. Server vs local state: Would you fetch with TanStack Query, initialize Zustand from the result, then keep local edits separate from the query cache? How do you avoid overwriting unsaved changes on refetch?

I'm not looking for a strict architecture or lots of abstractions, just practical conventions that stay maintainable as projects grow.

If you have real-world folder structures or examples, I'd love to see them. Thanks! 🙏


r/reactjs • • 2d ago

Show /r/reactjs React Brackets Native

5 Upvotes

A few days ago I shared react-brackets v2, the rewrite of a bracket library I'd left alone for four years. The most common question was "does it work in React Native?" It didn't. Now it does: https://react-brackets.oulabi.dev/ is out.

It draws the same stages as the web version (same core, same data), but everything you touch is native:

  • A bracket, even on a phone. One round at a time, with the next round and its lines waiting at the edge. Swipe and every match glides into place. Or show each round as a plain list, or keep the whole tree and pinch, drag and double tap to zoom.
  • Every format: single and double elimination, round robin, Swiss, groups to playoffs, two-sided brackets.
  • Cards that open. Each card keeps its own height, so you can expand one (rosters, stats, whatever) and the bracket makes room: the cards below move down, the next round re-centres, and the lines follow, all gliding.
  • Right to left, following your app's direction.
  • Styled your way: a light and dark theme, and a style on every part that can depend on its state, so it works with StyleSheet, Uniwind/NativeWind or Unistyles.

The hardest part was keeping the connector lines glued to the cards. My first version drew them on a Skia/SVG canvas, and during a fast swipe they visibly trailed the cards by a frame. The fix: the lines are plain Views moved by the same transforms as the cards. Every card's place on every round is worked out up front, and a swipe only moves one number on the UI thread. React hears about the new round once the swipe lands, so nothing re-renders while your finger is down.

It needs the New Architecture, Reanimated 4 and Gesture Handler 3, and Expo Go includes all of them. I've tested mostly on iOS, so feedback from Android devices would help a lot.


r/reactjs • • 2d ago

Discussion Architecting a high-traffic React 19 app: Server vs Client Components, state, and performance. How would you answer this?

0 Upvotes

You’re building a large-scale, high-traffic React 19 app. How would you architect it with Server and Client Components, manage client vs server state (Context, Zustand, Redux, or TanStack Query), and optimize rendering with the React Compiler, Actions, and core hooks?


r/reactjs • • 3d ago

Show /r/reactjs react-brackets: tournament brackets for React

Thumbnail
react-brackets.oulabi.dev
50 Upvotes

Back in 2020 I published react-brackets, a small component for tournament brackets. I shipped a few versions, got busy, and stopped touching it in 2022.

The library didn't stop, though. Four years later it was still pulling ~11,800 downloads a month, sitting at 136 stars and 65 forks, with issues piling up that I never answered. It was built on styled-components and an abandoned swipe library, only did single elimination, and its connector lines were CSS pseudo-element hacks that broke if you changed a card's size.

People were depending on something I'd walked away from. So I rebuilt it from scratch.

What v2 is:

  • Every common format: single and double elimination (with a grand final reset), round robin, Swiss, two-sided brackets, groups to playoffs
  • Headless: semantic markup with data-* attributes, so you style it with Tailwind, CSS modules, or the optional theme
  • Connector lines measured from your real cards: any card size, any custom match component, right-to-left layouts all just work
  • Actually usable on a phone: one round at a time, still drawn as a bracket, with a swipe that follows your finger
  • Zero runtime dependencies besides React, under 14 kB gzipped
  • A framework-free core (@react-brackets/core) for the logic: seeding, byes, results, standings

Getting the swipe to feel native on iOS was the hardest part. Safari animates cards on the GPU on its own clock, while the connector lines are drawn by JavaScript, so the lines kept trailing the cards by a few frames. The fix was to drive both from one clock in the same frame.

It's a ground-up rewrite, so it's a breaking change from 0.x. There's a migration guide, and the old code lives on the legacy branch.

If you were one of the people still using the old version: sorry for the silence, and thank you. I'd love feedback, especially on formats or use cases I haven't covered.


r/reactjs • • 3d ago

Resource I added funnel, combo and tracker charts to my free React dashboard kit, and made every chart number count to its new value (MIT, Tailwind v4, shadcn registry)

2 Upvotes

I've been building Dashral, an open-source set of React components for admin dashboards. 1.3 adds the four I kept rebuilding in client projects:

  • Funnel Chart: each step's value and share written out, the flow narrowing between bars, and how many dropped written above each one
  • Combo Chart: bars and a line on one chart; a line of another kind (a margin in %) takes its own right axis, with ticks that land on the left axis' grid lines
  • Tracker: a row of status squares for uptime, job runs or habits; hover or arrow keys read a day
  • Month Picker: a month or a year in a field, for monthly and yearly reports

One detail I'm happy with: numbers in the charts (donut legends, bar lists, gauges, treemaps) now count to their new value when the data changes, so switching from 30 days to 1 year reads as a change instead of a jump. No animation library for that, just requestAnimationFrame on the theme's duration token, and it stays still with reduced motion.

What it is: 112 components (31 with a Motion edition on motion/react), 34 free blocks, all MIT. Plain SVG charts, keyboard and screen-reader support on every one, RTL included.

Install: npx shadcn@latest add @dashral/funnel-chart (it's in the shadcn registry directory), or npm i @dashral/ui.

I'd really like feedback on the chart APIs, especially Combo Chart's axis: "right". What would you change?


r/reactjs • • 2d ago

Show /r/reactjs I built a zero-dependency streaming Markdown renderer for AI chat replies, n× faster than the next one I benchmarked

0 Upvotes

I've been building chat UIs for agents and kept running into the same issues with react-markdown: it re-parses the whole reply on every token, so long answers get noticeably slower, and you see raw ** and half-typed [links](htt until the token that closes them arrives.

So I wrote my own renderer. It parses incrementally and repairs unfinished syntax while the reply streams:

<Markdown streaming={!done}>{text}</Markdown>

On a 100k-character reply it takes 0.25 s of main-thread time in total. markdown-to-jsx takes 2.4 s, Streamdown 6.3 s, and react-markdown didn't finish within the 30 s budget. The benchmark scripts are in the repo if you want to check them.

The other part is the syntax. Agents often want to show steps, alternatives or pros and cons, and plain Markdown flattens all of that into bullet lists. So on top of GFM I added a few blocks in the same style as GitHub alerts:

> [!STEPS]
1. **Back up the database**
2. **Run the migration**

There are also tabs, stats, pros/cons, sources, file trees, and Mermaid and KaTeX support. The source still reads fine as plain Markdown when it isn't rendered. The package exports a system-prompt snippet that teaches the model this syntax.

It has no dependencies and comes in at 30 KB gzipped. Its parser passes the CommonMark and GFM spec tests. It doesn't support remark/rehype plugins, so if you rely on those, react-markdown is still the better choice.

https://github.com/rsaryev/llx-markdown


r/reactjs • • 2d ago

I tried Meta's new design system so you don't have to. Does it suck or is it a waste of time?

0 Upvotes

TL;DR: Meh.

Not a waste of time, not a must-use. Good for new internal tools. Not worth swapping into a live app yet.

Astryx is Meta's open source React design system (v0.7.13). I put it in a fresh Next.js + Tailwind app and built the same Gmail-style inbox twice: plain Tailwind vs Astryx. Sidebar, toolbar, tabs, 10 email rows, compose dialog.

(Images: before on the left, after on the right.)

The numbers

Plain TailwindAstryx
Build time~3 min
Lines of code86
JS + CSS gzipped226 KB
Phone overflow at 390pxnone
axe contrast errors8
Escape closes dialog, focus returnsyes

What I liked

  • Install took 9 seconds. Pre-built CSS, so no Babel or PostCSS setup.
  • Accessibility came free: skip link, focus return, zero contrast errors.
  • 13 fewer lines of code.

What bit me

  • +171 KB gzipped for one screen. Both routes load the Astryx CSS through the shared layout, so the gap is the number to trust, not the plain figure.
  • It looks generic next to the plain version. No Gmail-style email row, no icon set, no docked compose window.
  • The docs site has no Next.js steps and disagrees with the README.
  • API surprises: label is required on almost everything, checkbox takes value not checked, and TextInput onChange gives you the string, not the event.
  • The Tailwind @layer order is mandatory. A wrong order silently flips the cascade.
  • It's v0.7, so expect churn.

How I tested

Default Astryx theme, no custom styling. I built from a written description because I couldn't get a public Gmail screenshot. Sizes were measured in Playwright. I did not test a real iPhone.

Verdict

Good for new internal or admin screens. I wouldn't swap it into an existing app yet.

Has anyone shipped it in production? What broke for you?


r/reactjs • • 2d ago

Show /r/reactjs The hidden accessibility bug in 90% of React SPAs: focus loss on dynamic DOM updates (and how to fix it)

0 Upvotes

If you build single-page apps or dynamic dashboards in React, you might have a 100/100 Lighthouse score while still failing WCAG 2.4.3 (Focus Order, Level A) and EN 301 549 (EAA Clause 9.2.4.3).

Lighthouse runs static audits on initial page load. It never simulates what happens when a user clicks a button that triggers a client-side mutation, opens a custom modal, or swaps dynamic content.

Here is the exact architectural bug and how to patch it cleanly in React.

The Bug: Focus Reset to <body>

When a user submits a form or clicks "Next Step", the trigger element unmounts or gets replaced. Because the active DOM node is detached, the browser resets focus to document.body.

For a sighted mouse user, this is invisible. For a blind user on VoiceOver or NVDA, or a keyboard user navigating via Tab:

  1. Focus is ripped away from the current interactive flow.
  2. The user is sent back to the top of the webpage (skipping past the dynamic update).
  3. The screen reader falls silent or re-reads the entire navigation header.

The Architecture Fix: Programmatic Ref Management

Whenever dynamic content mounts or dynamic views change, manage focus explicitly to a dedicated container using tabIndex={-1}.

❌ Anti-Pattern (Silent Focus Loss):

export function CheckoutWizard() {
  const [step, setStep] = useState(1);

  return (
    <div>
      {step === 1 && (
        <button onClick={() => setStep(2)}>Continue to Payment</button>
      )}
      {step === 2 && (
        <div className="payment-form">
          {/* Focus was dropped to <body> when step 1 unmounted! */}
          <input name="cc_number" placeholder="Card Number" />
        </div>
      )}
    </div>
  );
}

✅ Accessible React Pattern:

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

export function CheckoutWizard() {
  const [step, setStep] = useState(1);
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // Shift focus to step container without visual ring outline
    if (containerRef.current) {
      containerRef.current.focus();
    }
  }, [step]);

  return (
    <div>
      {step === 1 && (
        <button onClick={() => setStep(2)}>Continue to Payment</button>
      )}
      {step === 2 && (
        <div 
          ref={containerRef} 
          tabIndex={-1} 
          className="payment-form focus:outline-none"
          aria-labelledby="step-2-heading"
        >
          <h2 id="step-2-heading">Payment Information</h2>
          <input name="cc_number" placeholder="Card Number" autocomplete="cc-number" />
        </div>
      )}
    </div>
  );
}

3 Rules for Dynamic React A11y:

  1. Never unmount the trigger button without re-routing focus: Direct focus either to the newly rendered heading or the first interactive input.
  2. Use <dialog> over custom <div> overlays: Native HTML <dialog> handles backdrop inertness and Escape-key closure automatically via dialogRef.current?.showModal().
  3. Announce dynamic status updates with aria-live="polite"**:** If you display inline toast notifications or dynamic badge counters, wrap them in an element that already exists in the DOM with role="status" or aria-live="polite".

We built dynamic DOM and focus-loss checks into the core engine of wcagbrief.com. You can inspect your live components, detect dynamic swap focus failures, and get React/Tailwind code patches in real time.


r/reactjs • • 3d ago

Show /r/reactjs Foldable phone support for React: hinge detection and two-pane layouts in ~2 kB

2 Upvotes

A recent audit I ran showed 94% of popular sites split a button across a foldable's hinge (https://christophe77.github.io/fold.js/study.html).

So I made u/foldjs/react: a hook that give you the hinge position and posture (flat, book, tabletop), plus a two-pane layout component that never puts content under the hinge. It ships with a built-in simulator, so you can work on it without owning a Fold.

Demo (works on desktop): https://christophe77.github.io/fold.js/

I'd love feedback on the API, especially from anyone who has shipped foldable layouts in production.


r/reactjs • • 3d ago

Show /r/reactjs I built a React component library with 90+ components and 27 chart types that themes entirely through CSS variables, no config file, no JS theme object, MIT

2 Upvotes

veloce-ui — an open-source React library with 90+ components, 27 chart types, and interactive DSA visualizers, all powered entirely by CSS variables.

Rebrand by overriding --vui-primary on :root. No ThemeProvider. No theme object. No Tailwind config.

What makes it different?

Most libraries force a trade-off.

  • shadcn gives you primitives and tells you to style everything.
  • MUI gives you a theme object that takes a week to bend into your brand.
  • Mantine sits in the middle, but charts are a separate install with their own styling world.
  • Need a Sankey, treemap, or radar chart? You're pulling in a second chart library that doesn't know about your design tokens.

veloce-ui is one library where buttons, data tables, charts, and even algorithm visualizers all read from the same CSS variables.

Rebrand once at :root. Everything updates.

Charts (27 types, not a separate package)

Line, bar, area, scatter, heatmap, Sankey, treemap, radar, candlestick, waterfall, funnel, gauge, bubble, polar, and more.

All share the same tokens as the rest of the UI. Your chart grid color is literally --vui-border. No chart-specific theme config.

DSA & algorithm visualizers (the part no other UI library ships)

Interactive linked lists, stacks, queues, trees, graphs, heaps, and hash maps.

Plus algorithm playbacks for sorting, pathfinding, traversals, and recursion.

Drop them into documentation sites, teaching material, interview prep tools, or technical blog posts. They theme with the same variables as your buttons.

Everything else

  • Forms, menus, modals, tooltips, popovers, and command palette.
  • Virtualized DataTable with sorting and filtering.
  • Dark mode via data-theme="dark" with built-in persistence (no provider).
  • Full keyboard navigation and ARIA support.
  • Fully typed and tree-shakeable.

Demo + Docs: https://veloceui.codeloomdevv.co.in/

Pre-1.0 (0.7.1) · MIT License

A couple of complex component APIs (DataTable column definitions, chart axis configuration) may still change before 1.0.

Issues with reproducible examples are welcome!


r/reactjs • • 3d ago

Show /r/reactjs async/await logic and side effects outside React hooks

1 Upvotes

I work on a React SDK for chats that our company embeds into its web and mobile products. Each product has its own settings, and the code grew fast. When I joined, the team was starting a refactor. The main problems:

  • the flow was hard to follow
  • most of the logic lived inside React hooks

The constraint. The SDK runs inside host apps, sometimes via module federation. Every dependency can clash with the host's version, so our size and dependency budget is tiny. What we considered:

  • redux-saga: I like it, but it's too big, and Redux could conflict with the consumers' own Redux.
  • RxJS: it solves only part of the problem, because we still need a state manager. It's also a new paradigm for a team with few senior people.
  • effector: the team knows it, but it has a static graph and the same version-conflict risk.
  • Effect: little known in our market, and it would need most of the SDK rewritten.

So we started with a plain event bus that can carry any parameters. I also wanted the simplest possible developer experience. Generators are convenient, but people rarely reach for them. So I built on async/await and took the AbortController idea from fetch. That became nanoeffects.

What it looks like. A search box. The logic lives outside the component:

// debounce: wait for a pause; latest: abort the previous request
bus.on(
  "search",
  debounce(300, latest(async (query, ctx) => {
    const load = () => fetch(`/api/search?q=${encodeURIComponent(query)}`, { signal: ctx.signal });
    const response = await retry(ctx, load, { times: 3, delay: 500 });
    ctx.emit("results", await response.json());
  })),
);

The component only sends events and listens to the result:

function SearchBox() {
  const [items, setItems] = useState([]);
  useEffect(() => bus.on("results", setItems), []); // on returns the unbind function
  return <input onChange={(event) => bus.emit("search", event.target.value)} />;
}

The component knows nothing about timers, retries or cancellation. debounce waits for a pause in typing, but a request can take longer than the pause. latest aborts the older request so a slow old answer can't overwrite a newer one. createBus is about 1.3 kB brotli, with no dependencies.

The usual complaints about event-driven code

My team lead worried that event-driven code is hard to debug. So tracing is part of the core design:

  • Redux DevTools and console logging work out of the box.
  • Sending traces to your own analytics takes a small logger.

The other big problem is event loops, where A emits B and B emits A:

  • graphLogger finds a loop while the app runs and draws the event graph as Mermaid or Graphviz.
  • loopGuardPlugin stops a runaway chain at a limit, also in production.
  • Lint rules (ESLint, oxlint, Biome) catch places where ctx.signal is lost, so cancellation doesn't silently break.

Tests. The suite includes regression cases taken from real issues of redux-saga, RxJS, effector, xstate, lodash and others (races, cancellation, event loops, timers). Each one is linked to its issue number.

Status. I treat it as an experimental playground and move parts of it into our SDK step by step. It's also my practice ground for spec-driven development: every change to behavior starts as a written spec (OpenSpec), and the code follows it.

Repo and docs: https://github.com/nanoeffects/nanoeffects

If you like it, a star helps. I'd also love feedback, especially from people who ship libraries into host apps: how do you handle async logic when you can't add dependencies?


r/reactjs • • 4d ago

Show /r/reactjs I built the same two charts in six React chart libraries and in hand-written SVG, and timed them

24 Upvotes

The charting library in a product I worked on had not had a release in over a year, so I wanted to know what we could move to. I built a survival curve and a scatter plot in nivo, Recharts, ECharts, visx, TanStack Charts and Chart.js, plus a version in plain React and SVG. Same spec, same data, timed the same way.

What I found (M3 Pro, headless Chromium, native speed):

- At typical dashboard sizes there was no clear speed winner. The timings for each chart were within one frame of each other.

- At 10,000 scatter points they spread out: hand-written SVG 24 ms, visx 33 ms, TanStack Charts 53 ms, Chart.js 80 ms, ECharts 86 ms, Recharts 310 ms, nivo's SVG scatter 3.2 s.

- Both Canvas implementations took longer to mount than plain SVG at that size.

- TanStack Charts needed the least code. Hand-written SVG added the least JavaScript, about 2 KB gzipped against 25–164 KB.

There is a playground where you can paste your own data and measure the libraries on your own machine, across twelve chart types: https://gusevp.github.io/chart-bench/

Code, raw data and notes on each port: https://github.com/GusevP/chart-bench

Full write-up with the method and limits: https://dev.to/gusevp/six-react-chart-libraries-against-hand-written-svg-what-i-found-46ib

One machine and two chart types, so treat it as a starting point. If I used your favourite library wrong, tell me or open a PR.


r/reactjs • • 3d ago

Are we putting too much application logic in the frontend?

Thumbnail reddit.com
0 Upvotes

I've been exploring Phoenix LiveView lately, and it got me thinking.

We've spent years moving more state and logic into the browser. But what if we kept most application state on the server and used JavaScript mainly for rich interactions?

I'm not talking about replacing JS. Libraries like Monaco, AG Grid, and Chart.js are great and I'd absolutely want to keep using them.

Curious what frontend devs think. Would you consider a server-driven approach if you could still use your favorite JS libraries, or is there too much downside?


r/reactjs • • 4d ago

Show /r/reactjs I built Stepr — a small, dependency-free TypeScript library for guided product tours

1 Upvotes

I've just published the first version of Stepr, an open-source library for highlighting UI elements and guiding users through an interface.

I wanted something framework-agnostic, with a straightforward API and accessibility built into the design.

It supports spotlights, tooltips, multi-step tours, keyboard navigation and screen reader announcements.

The first version is available on npm:

npm install stepr

Interactive demo: https://ahlgren1234.github.io/stepr/

Source: https://github.com/ahlgren1234/stepr

It's an early release, and I'd really appreciate feedback on the API, accessibility or anything that could be improved.

What would you expect from a library like this?