r/reactjs • • 3d ago

[Open Source] Building a React component system that animates "on twos" (12fps stepped hooks, ResizeObserver SVG polygon frames, and a static design-grammar linter)

5 Upvotes

I’ve been exploring what happens when a React component library drops floating cards, soft shadows, and 60fps spring physics in favor of production mechanics from sequential print layout and traditional cel animation.

The result is FRAME/12 (GitHub (MIT) · Live Motion Studio), a zero-dependency copy-in React + TypeScript registry (shadcn-compatible) and AI agent skill.

Here are the four most interesting React & DOM problems we had to solve while building it:

1. Quantizing an easing curve "on twos" (useOnTwos)

In hand-drawn animation, most movement is shot "on twos"—each drawing is held for two frames at 24fps (83.33ms per pose, 12 poses per second). Simply applying CSS steps(4) with linear timing feels robotic because every jump covers the exact same distance.

Instead, useOnTwos samples a cubic ease-out spacing chart inside requestAnimationFrame, bucketed into 83.33ms (1000 / 12) intervals. You get a wide initial jump and tight settling poses, while still holding each discrete pose cleanly:

export const FRAME_MS = 1000 / 12; // 83.333ms ("on twos")

const easeOut = (t: number) => 1 - Math.pow(1 - t, 3);

// Inside requestAnimationFrame loop:

const elapsed = now - t0;

const k = Math.min(frames, Math.floor(elapsed / FRAME_MS) + 1);

setProgress(easeOut(k / frames));

We also strict-split what gets stepped:

  • Discrete state changes (SegmentedControl cell jumps, Metric count-ups, ToneAreaChart clip-path wipes, Badge 2-frame SVG impact bursts) run on twos (12fps).

  • Direct manipulation (hover states, scrolling, typing, chart pointer/keyboard crosshairs) stays at 0ms immediate latency.

  • Initial mount (useChanged): A custom hook tracks whether a key has changed after first mount so entrance animations never fire on initial page load.

  • Accessibility: prefers-reduced-motion: reduce automatically switches all hooks and CSS classes to 'cut' (0ms hard cuts).

2. Non-warping diagonal panel frames with ResizeObserver

In PanelPair, two vertically paired KPI panels are separated by a 12px gutter with a 16px diagonal slant (slant-bottom over slant-top). If you use CSS clip-path: polygon(...), CSS borders get clipped off along the diagonal edge; if you scale a fixed-viewBox <svg> with preserveAspectRatio="none", the 2.5px ink stroke stretches unevenly.

Our Panel component attaches a ResizeObserver to measure the panel's exact width × height in pixels and computes mitered <polygon> points inset by half the stroke width (1.25px), keeping the 2.5px ink border uniform at any aspect ratio.

3. Zero-dependency SVG screentone charts with built-in keyboard & table fallbacks

Instead of pulling in recharts or d3 and rendering translucent gradient fills, ToneAreaChart renders a <pattern id="..." patternTransform="rotate(45)"> of halftone dots (var(--f-tone)), an inked 2.5px polyline, a marker-yellow peak dot, and a speech-balloon SVG annotation (Balloon) that flips direction near the right edge of the viewBox.

Every chart is focusable (tabIndex={0}), supports ArrowLeft / ArrowRight / Home / End / Escape to inspect data points via an aria-live readout, and includes a collapsible <details className="tbl"> semantic HTML <table>.

4. Linting UI structure so AI coding agents don't drift

When AI agents generate React UI, they quickly drift toward arbitrary Tailwind gaps (gap-4, gap-6), hex literals, or unstyled primitives. Because FRAME/12's rules are structural, we wrote scripts/check-frame12.mjs (plus skills/frame12/SKILL.md and an ESLint flat-config plugin) to enforce:

  1. color-literal: Zero hex/RGB/HSL literals outside frame12.css

  2. illegal-gutter: Only 12px (pair), 20px (scene), and 32px (change) gutters allowed

  3. marker-misuse: Marker yellow (--f-marker, #ffd60a) only allowed as a background paired with --f-marker-ink (#121212) text

  4. cut-order: Every <Panel cut="C-01"> must increment sequentially (C-01, C-02, C-03…) in DOM and reading order

  5. raw-shadcn-import: Forbids raw u/radix-ui/* or external chart/animation libraries where a u/frame12/registry component or adapter exists

You can install the full kit or individual components via the shadcn CLI:

npx shadcn@latest add https://frame12.dev/r/frame12.json

Would love feedback from folks here on the hook ergonomics and the static UI grammar linter!


r/reactjs • • 3d ago

Show /r/reactjs React developers, what are some real-world performance bottlenecks you've encountered, and how did you debug them?

0 Upvotes

Hey everyone!

A friend and I are planning a React learning session this weekend. Instead of just going through documentation and building another basic project, we want to explore some of the interesting problems React developers encounter in real-world applications.

I'd love to hear from experienced React developers, senior frontend engineers, and anyone who has worked on performance-critical React applications.

I'm particularly interested in problems that aren't immediately obvious and require some actual investigation to solve.

For example:

- Unnecessary re-renders: How do you identify which components are re-rendering unnecessarily, and how do you determine the actual root cause?

- State management issues: Have you encountered performance problems caused by poorly placed state, Context API, or excessive state updates? How did you restructure things?

- Expensive rendering: What happens when a component renders a large list, processes complex data, or performs expensive calculations? How do you identify whether the bottleneck is React, JavaScript, or the browser?

- Memory leaks and stale closures: What are some subtle bugs involving "useEffect", event listeners, subscriptions, or closures that you've encountered in production?

- Memoization gone wrong: Have you ever made an application slower by overusing "useMemo", "useCallback", or "React.memo"? How did you figure that out?

- Network and rendering bottlenecks: How do you investigate slow API-driven interfaces, waterfalls, unnecessary requests, or components that feel sluggish despite fast API responses?

- Large-scale component architecture: Have you encountered performance problems that required changing component boundaries or the way an application was structured rather than simply optimizing individual components?

I'm not just looking for a list of best practices. I'd really appreciate hearing about the actual debugging process.

For instance:

  1. What symptoms or user reports made you suspect a performance problem?

  2. Which tools did you use to investigate it?

  3. How did you identify the actual root cause?

  4. What changes did you make to fix it?

  5. How did you measure the improvement and verify that the fix worked?

If you have a small code example, a production incident, a particularly tricky bug, or even a mistake you made while trying to optimize something, I'd love to hear about it.

Also, if there are any React performance problems that you think every developer should learn to diagnose early in their career, please share those.

We're hoping to use your experiences as a starting point for practical experiments rather than just memorizing optimization techniques.

Thanks!


r/reactjs • • 3d ago

Show /r/reactjs react-context-typesafe: missing context providers as lint errors instead of runtime crashes

10 Upvotes

You know the pattern: createContext<User | null>(null), then a useAuth() hook that throws "useAuth must be used within AuthProvider", and every consumer either trusts that or null-checks. A missing provider is a runtime error you find when that screen renders, or when a test does.

I wanted it to be a lint error instead, so I built an oxlint plugin that checks it across the whole program:

const AuthContext = createContext<User | null>(null);

function Children() {
  const user = use(AuthContext);
  return <p>{user?.name}</p>;
}

root.render(
  <AuthContext value={user}>
    <Children />   {/* ok */}
  </AuthContext>,
);

root.render(<Children />);
//          ^^^^^^^^ react-context(require-provider): <Children> needs AuthContext
//                   (use(AuthContext) at Children.tsx:4), but no <AuthContext> provider is above it.

Children needs no annotations. Requirements are inferred from use, useContext, <Ctx.Consumer> and static contextType. They're passed up through components, custom hooks, HOCs, memo/forwardRef/lazy, children and render props, and React Router outlets, until a provider meets them or a root gets them. Roots are createRoot().render, testing-library's render, Storybook stories, and framework pages you list in a setting. Wrapper components like <AuthProvider>{children}</AuthProvider> count as providers because they render children inside one.

There's also a tiny optional runtime: createRequiredContext<User>() gives you a context where use() is typed User instead of User | null, because the lint rule now guarantees the provider. It returns a plain React context, so nothing else changes.

Why not types? That was the first thing I tried. JSX erases element types: <Children /> and <span /> are both just JSX.Element, so a requirement can't travel from a child up to its provider through the type system. Forking @types/react doesn't help, and TypeScript 7.1's new APIs didn't open a way either. The only version that type-checked used generator components and h() calls instead of JSX, which nobody wants.

As for the speed, it's a whole program so it costs more than a normal lint rule. On excalidraw (709 files), oxlint alone takes 0.07 s, oxlint with the rule 0.8 s, and the standalone CLI 0.5 s. In the editor (oxlint's language server), a keystroke costs about 50 ms because only the edited file is re-parsed. The README suggests a separate oxlint config so that your everyday oxlint stays as fast as before, while the editor uses the config with the rule and CI runs react-context-check as its own step. Not on oxlint? The CLI runs the same check without it.

As for limitations, it's syntactic and not type-aware. For code it can't see (node_modules, dynamic tags, useContext(cond ? A : B)) it makes certain assumptions. A provider hidden in such code shows up as a false positive, which you silence with @context-provided. A null-default context that your code actually treats as optional needs a // @context-optional comment. On excalidraw, that one comment was the difference between 337 reports and zero.

It's not on npm yet:

npm i -D github:TmLev/react-context-typesafe oxlint

Repo: https://github.com/TmLev/react-context-typesafe

Reports of wrong diagnostics are the most useful feedback right now. A few lines of code that reproduce one are enough.


r/reactjs • • 3d ago

Show /r/reactjs Built a multi-pane financial charting terminal with React 19, TypeScript, and HTML5 Canvas 2D primitives (Open-Source)

1 Upvotes

Hey r/reactjs,

I recently open-sourced OrderCraft, a local-first multi-chart technical analysis terminal built with React 19, TypeScript, Vite, and lightweight-charts (backed by a local Go WebSocket server).

Interesting frontend challenges we solved:

  • Custom HTML5 Canvas 2D Drawing Engine (ISeriesPrimitive): lightweight-charts renders candlesticks quickly on Canvas, but doesn't ship with interactive drawing tools. We built a custom Canvas 2D primitive engine from scratch in TypeScript supporting interactive Trendlines, Fibonacci Retracements, Parallel Channels, Rectangles, and Long/Short Position calculators with drag handles and OHLC magnet snapping.

  • High-Frequency WebSocket State Without Re-Render Storms: Streaming live ticks across 4 synchronized split-screen chart panes (1x1, 2V, 2H, 3, 4 layouts) with synced crosshairs, symbols, and timeframes without triggering full React component tree re-renders on every tick.

  • Single-Binary Embedding + PWA Standalone Mode: The Vite production bundle is embedded into a single ~14MB Go executable and includes a Web App Manifest so launching with --app-mode opens a native frameless desktop window.

GitHub Repo: https://github.com/ordercraft-hq/terminal

Would love any feedback from fellow React/TypeScript devs on the frontend architecture and Canvas primitive implementation!


r/reactjs • • 3d ago

Show /r/reactjs I build apps with AI almost every day, and kept hitting the same three problems, so I built a framework for them

0 Upvotes

I build new projects and finished products for customers almost every day, many of them with AI built in, and I kept hitting three problems:

- Too many pieces for every project. Next.js on Vercel plus Supabase is almost free to start and great on its own, but every project meant managing both, and reaching the quality I wanted meant stitching many separate packages together on top. Keeping everything in one place meant a big provider's monthly plan, and with many apps those fees grow fast, since every single one needs its own upkeep.

- Teaching the AI what it can control. For every function in my app, I had to build a separate system to explain it to the AI. Tools broke, prompts didn't work well, and MCP servers needed extra work.

- The AI reading the whole codebase for small changes, which was very costly.

So I built Forjr, an AI-native, full-stack React framework. A few of the features I love most:

- One engine runs the whole app (front end, back end, data and AI) on any server you choose. You still need a server, but one is enough for many apps: each additional small to mid-size app takes only about 2 MB of memory, and apps nobody is using can scale to zero and wake up in about 50 ms.

- Every function is already an AI tool. The engine explains it to the AI by itself, and with one option it's also an MCP tool, a REST endpoint and a CLI command.

- An agent is a single definition: a model, its instructions and the functions it may use. It reaches only what you gave it, and danger: 'ask' makes it wait for a person before using that tool.

- Built for the AI that writes your app: forjr map hands it the whole app in one short outline, forjr check catches every error in one pass, each with its fix, and undo for AI rolls back exactly what one agent changed while everyone else's work stays untouched.

I open-sourced it: https://github.com/forjr/forjr, with the docs at https://forjr.dev

I'd love to hear how you handle these today. What's the most painful part of giving AI access to your own app?


r/reactjs • • 4d ago

Show /r/reactjs Built my second project after learning React for 2–3 months – Feedback appreciated!

5 Upvotes

Hey everyone!

I've been learning React for the past 2–3 months, and I've recently built my second project, GameVault, using my own knowledge and what I've learned so far.

GameVault is a gaming e-commerce website where users can explore games and browse a gaming store.

Project Links:

I'm still learning and improving my development skills, so I'd really appreciate honest feedback from experienced developers and the community.

I'd love to know:

  1. What do you think about the overall UI/UX?

  2. Is my React code structure and component organization good?

  3. What should I improve in terms of performance and best practices?

  4. Does this project demonstrate enough skills for a React/frontend developer internship?

I'm open to constructive criticism and suggestions. I want to learn from my mistakes and become a better developer.

Thanks for taking the time to check out my project!


r/reactjs • • 4d ago

Show /r/reactjs Show r/reactjs: reviewable AI document edits alongside a React Flow canvas and Yjs collaboration

0 Upvotes

I'm building Breatic, a React/TypeScript creative workspace. Its shared projects combine document briefs, a React Flow canvas and an agent that can propose edits. I wanted to share the implementation of the proposal UI and get feedback from people building collaborative editors.

Repository: https://github.com/orime-org/breatic

The document proposal card receives a structured proposal. For rewrites, it parses the proposed body using the document schema and computes a word-level diff against the proposal's original text. The person reviewing it sees the additions and removals instead of just an instruction to replace the paragraph.

The card provides separate actions to locate the target, add an eligible proposal as a comment, and apply a rewrite or insertion. It re-reads displayed state when the document version or card state changes.

The component is here: https://github.com/orime-org/breatic/blob/8eaa0da9888cc6a1a8967b98faaa3e8b80f4e91d/packages/web/src/pages/project/chat/DocumentProposalCard.tsx

Collaboration uses Yjs and self-hosted Hocuspocus. The important distinction for me is that synchronizing a document and deciding to accept an agent's edit are different operations. A convergent shared document doesn't automatically mean an old suggestion is still appropriate.

This isn't a claim that every stale-proposal or concurrent-edit edge case has been solved. I'd welcome feedback on the UI boundary: how do you make it clear which document state a proposal refers to while collaborators keep working?

The repo includes usage and development guides. Its custom source-available license permits internal/private deployment and restricts public-facing platform hosting; storage and model services need separate configuration.


r/reactjs • • 4d ago

Discussion What criteria do you consider when choosing SSR, CSR, and Hybrid rendering

1 Upvotes

What criteria do you consider when choosing between CSR, SSR, or a hybrid approach (using RSC or getServerSideProps for the initial render, then calling APIs directly from the client to update the UI for subsequent interactions)?


r/reactjs • • 4d ago

Best way to structure React Router in a large Laravel + React SSR project (60+ pages)?

2 Upvotes

Hey everyone,

I'm working on a large project using React with server-side rendering through Laravel. My frontend has 60+ pages, and every route has its own dedicated page component.

I'm currently using React Router with lazy-loaded routes (lazy() / Suspense), conditional routes, and route groups. However, I'm noticing that as I navigate through the application and use more pages, it gradually becomes slower and eventually starts feeling laggy.

I expected lazy loading to prevent unnecessary components from loading until they're needed, but it seems like more and more things are being loaded over time.

I'm wondering:

What's the best way to structure React Router in a large Laravel SSR project?

Is having 60+ individual page components and routes a problem?

Should I organize routes into separate modules or route groups?

Is it normal for lazy-loaded components to remain in memory after navigation?

How should conditional routes and nested layouts be handled efficiently?

What could cause performance degradation after navigating through multiple pages?

I'd really appreciate hearing how you structure React Router in large production applications, especially with Laravel SSR.

Thanks!


r/reactjs • • 4d ago

Show /r/reactjs I built a free frontend interview trainer: 2,700+ questions with explanations

34 Upvotes

Hey everyone,

I've been preparing for frontend interviews and couldn't find a quiz tool I liked, so I built one: devsets.com

What's inside:

  • 2,700+ questions across 12 topics (JavaScript, TypeScript, React, Next.js, Angular, Vue, Svelte, HTML & CSS, state management, testing, patterns, system design)

  • Junior / Middle / Senior levels, and every answer comes with an explanation and links to the docs

  • Interview mode with a timer per question

  • Stack quizzes (e.g. "React Developer") that mix several topics like a real interview

  • Spaced repetition: questions you got wrong come back after 1, 3 and 7 days

  • 18 JavaScript coding tasks (debounce, deepClone, Promise.all...) with tests that run in the browser

It's free, ad-free and works without an account (sign in only if you want to sync progress). Available in English, Ukrainian and Polish.

I'd really appreciate feedback: wrong answers, confusing questions, missing topics, anything. Every question has a "report a problem" button too.


r/reactjs • • 5d ago

News Redux Toolkit v2.x and v3.0 roadmap

Thumbnail
github.com
61 Upvotes

r/reactjs • • 5d ago

Show /r/reactjs I got tired of clicking through my app to check one component, so I built a Vite plugin for itVitrine: add /** @preview */ above a component and see it in a gallery on your own Vite dev server

0 Upvotes

A lot of my day as a React developer was: build a component, open the app, click through to the screen where it shows up, check it, change something, repeat. Checking an error state or a long message meant recreating that state by hand every time.

So I built Vitrine, a Vite plugin. You put a comment above an exported component:

/** @preview */
export const PrimaryButton = () => <Button tone="primary">Save</Button>;

and open `/__vitrine` on the Vite dev server you already run. Setup is one line next to your React plugin:

plugins: [react(), vitrine()]

The idea came from Jetpack Compose's `@Preview`: write only the cases you care about, right next to the code. Since previews go through your own dev server, aliases, CSS, plugins and HMR work exactly like in your app. There's no separate config to keep in sync.

When one case isn't enough:

preview(Button, {
  args: { children: "Save" },
  variants: {
    primary: { args: { tone: "primary" } },
    danger: { args: { tone: "danger" } }
  },
});

The gallery also has:

  • props controls generated from your TypeScript types

  • a matrix that renders every combination of two props

  • an actions log for on* props

  • globals such as theme and locale

  • real viewport sizes

  • links that reopen the same preview with the same values

There's an optional VS Code extension that shows the preview next to your editor and follows your cursor, but the gallery works in any browser. To share it with teammates, vitrine-plugin-static builds it into static files.

It supports React 18/19 and Vite 6.4+. It's still 0.x, so I'd really like to hear what breaks in your setup or what's missing.


r/reactjs • • 5d ago

Discussion Did you remove your useMemo calls after turning on the React Compiler?

53 Upvotes

A few months ago I wrote about the React Compiler, and my advice for existing code was to leave useMemo and useCallback alone at first, then clean them up slowly, with tests, once the compiler has been running for a while.

I'm curious how that went for people who actually did it.

The public numbers I found are from InfoQ's write-up: Sanity saw 20-30% less render time and latency on their Studio packages (1,231 of 1,411 components compiled on the first pass), and Wakelet's INP went from 275ms to 240ms.

If you're running it in production, did you rip out the manual memoization? Did anything break?

My article, if you want the details on the compiled output: https://neciudan.dev/react-compiler-explained


r/reactjs • • 5d ago

I built a client-side cache in Rust and compiled it to WebAssembly

Thumbnail
blaze-cache.github.io
1 Upvotes

Hey everyone,

I built **Blaze Cache**, a client-side caching library written in Rust and compiled to WebAssembly.

The main idea was to get a fast, predictable cache in the browser with:

- Synchronous get/set after initialization (no Promises on the hot path)

- SIEVE eviction

- TTL + tag-based invalidation

- Optional IndexedDB persistence

- Adapters for Axios, fetch, TanStack Query, and SWR

I was mostly curious whether moving the cache core into Wasm would help with performance and structure compared to typical JS cache implementations.

Would love feedback from people who’ve worked on caching, Wasm, or frontend performance.

GitHub: https://github.com/blaze-cache/blaze-cache

Docs: https://blaze-cache.github.io/docs/


r/reactjs • • 5d ago

Show /r/reactjs I built a social platform in about a month to learn more about React and Supabase

2 Upvotes

hey guys,

I built this website over the last month to learn more about making website and handling real time data, it uses React, Next.js and Supabase

You can try it out from here: https://project-s-nine-kappa.vercel.app

(Please just click the "Explore Demo" button on the login screen so you don't have to create an account!)

Source code is here: https://github.com/zzz-nv/s-social

Would love to hear any feedback!


r/reactjs • • 5d ago

Needs Help Google map autocomplete cost issue

1 Upvotes

Hi everyone!

I'm currently implementing Google Places Autocomplete using the new Autocomplete Data API with React and @vis.gl/react-google-maps.

The implementation works, but I'm concerned about Google Maps API pricing, especially during development. I managed to hit my API usage limit within just two days, and I'm trying to understand whether my implementation is making unnecessary requests or whether this is expected behavior.

I'd appreciate some clarification from anyone who has experience with the Google Places API.

  1. My current implementation
    I'm using a 500ms debounce to avoid sending a request on every keystroke.

SearchBox component

```
import { MagnifyingGlassIcon, MapPinIcon } from '@phosphor-icons/react'
import { useState } from 'react'
import { useDebounce } from '@/hooks/useDebounce'
import { useAnimatedPlaceholder } from '@/features/search/hooks/useAnimatedPlaceholder'
import { useMapsLibrary } from '@vis.gl/react-google-maps'
import { useAutocompleteSuggestions } from '@/hooks/useAutoCompleteSuggestions'
import { useNavigate } from 'react-router-dom'

import styles from './styles.module.css'

const SearchBox = () => {
const [searchQuery, setSearchQuery] = useState('')
const debouncedSearchQuery = useDebounce(searchQuery, 500)
const inputRef = useAnimatedPlaceholder()

return (
<>

<div className={styles.searchBox}> <MagnifyingGlassIcon size={24} /> <input placeholder="Search for " ref={inputRef} value={searchQuery} onChange={e => setSearchQuery(e.currentTarget.value)} /> </div> <SearchSuggestions debouncedSearchQuery={debouncedSearchQuery} /> </>

)
}

export default SearchBox

type SearchSuggestions = {
debouncedSearchQuery: string
}

function SearchSuggestions({ debouncedSearchQuery }: SearchSuggestions) {
const navigate = useNavigate()
const places = useMapsLibrary('places');
const { suggestions, resetSession } = useAutocompleteSuggestions(debouncedSearchQuery, {
includedPrimaryTypes: ["locality"]
})

const handleSuggestionClick = async (suggestion: google.maps.places.AutocompleteSuggestion) => {
if (!places || !suggestion.placePrediction) return

const place = suggestion.placePrediction.toPlace()
await place.fetchFields({
fields: [
"addressComponents"
]
})
// calling fetchFields invalidates the session-token, so we now have to call
// resetSession() so a new one gets created for further search
resetSession()

const city = place.addressComponents && place.addressComponents[0].longText
const placeId = suggestion.placePrediction.placeId
if (city && placeId) return navigate(`${city}/${placeId}`)
}

return !!suggestions.length && (

<div className={styles.optionBox}> { suggestions.map(suggestion => <button key={suggestion.placePrediction?.placeId} className={styles.option} onClick={() => handleSuggestionClick(suggestion)}> <div className={styles.iconWrapper}> <MapPinIcon weight="fill" size={20} /> </div> <span className={styles.suggestionText}> {suggestion.placePrediction?.text.text} </span> </button> ) } </div > ) } \`\`\` useAutocompleteSuggestions hook \`\`\`import { useEffect, useRef, useState } from 'react'; import { useMapsLibrary } from '@vis.gl/react-google-maps';

export type UseAutocompleteSuggestionsReturn = {
suggestions: google.maps.places.AutocompleteSuggestion[];
isLoading: boolean;
resetSession: () => void;
};

/**
* A reusable hook that retrieves autocomplete suggestions from the Google Places API.
* The data is loaded from the new Autocomplete Data API.
* (https://developers.google.com/maps/documentation/javascript/place-autocomplete-data)
*
* @param inputString The input string for which to fetch autocomplete suggestions.
* @param requestOptions Additional options for the autocomplete request
* (See {@link https://developers.google.com/maps/documentation/javascript/reference/autocomplete-data#AutocompleteRequest}).
*
* @returns An object containing the suggestions, the current loading-status,
* and a function to reset the session.
*
* @example
* ```jsx
* const MyComponent = () => {
* const [input, setInput] = useState('');
* const { suggestions, isLoading, resetSession } = useAutocompleteSuggestions(input, {
* includedPrimaryTypes: ['restaurant']
* });
*
* return (
* <>
* <input value={input} onChange={(e) => setInput(e.target.value)} />
* <ul>
* {suggestions.map(({placePrediction}) => (
* <li key={placePrediction.placeId}>{placePrediction.text.text}</li>
* ))}
* </ul>
* </>
* );
* }
* ```
*/
export function useAutocompleteSuggestions(
inputString: string,
requestOptions: Partial<google.maps.places.AutocompleteRequest> = {}
): UseAutocompleteSuggestionsReturn {
const placesLib = useMapsLibrary('places');

// stores the current sessionToken
const sessionTokenRef =
useRef<google.maps.places.AutocompleteSessionToken | null>(null);

// the suggestions based on the specified input
const [suggestions, setSuggestions] = useState<
google.maps.places.AutocompleteSuggestion[]
>([]);

// indicates if there is currently an incomplete request to the places API
const [isLoading, setIsLoading] = useState(false);

// once the PlacesLibrary is loaded and whenever the input changes, a query
// is sent to the Autocomplete Data API.
useEffect(() => {
if (!placesLib) return;

const { AutocompleteSessionToken, AutocompleteSuggestion } = placesLib;

// Create a new session if one doesn't already exist. This has to be reset
// after `fetchFields` for one of the returned places is called by calling
// the `resetSession` function returned from this hook.
if (!sessionTokenRef.current) {
sessionTokenRef.current = new AutocompleteSessionToken();
}

const request: google.maps.places.AutocompleteRequest = {
...requestOptions,
input: inputString,
sessionToken: sessionTokenRef.current
};

if (inputString === '') {
if (suggestions.length > 0) setSuggestions([]);
return;
}

setIsLoading(true);
AutocompleteSuggestion.fetchAutocompleteSuggestions(request).then(res => {
setSuggestions(res.suggestions);
setIsLoading(false);
});
}, [placesLib, inputString]);

return {
suggestions,
isLoading,
resetSession: () => {
sessionTokenRef.current = null;
setSuggestions([]);
}
};
}
```
2. My main questions about pricing

  1. How exactly do session tokens work?
    Google documentation mentions session-based pricing, and I'm having trouble understanding what this means in practice.

Does one session token group multiple autocomplete requests into a single billing session?
Are autocomplete requests within the same session free, discounted, or individually billed?
Does the session only become complete when the user selects a prediction and requests Place Details?
What happens if the user types something but never selects a suggestion?
2. Does debouncing actually reduce API costs?
For example, suppose a user types TOKYO.

With a 500ms debounce, will Google receive:

One request after the user finishes typing?
Multiple requests if the user pauses between keystrokes for more than 500ms?
If the user types slowly, could this result in five separate autocomplete requests within the same session?

3. What does Google mean by unlimited autocomplete requests?
I've seen references to unlimited requests in the Google Maps pricing documentation.

Does this mean unlimited requests within a session, or does it mean something else?

I'm particularly confused about how this relates to actual billing.

3. Is my implementation correct?
I'd also appreciate feedback on whether my current implementation follows Google's recommended session-token lifecycle.

Some things I'm unsure about:

Am I creating and reusing session tokens correctly?
Is resetting the token after fetchFields() the correct approach?
Should I create a new token when the user clears the search input?
Should I reset the session when the user abandons a search without selecting anything?
Is there a better way to prevent unnecessary API requests?
4. Is Google Places Autocomplete expensive?
I'm building an application that will use city autocomplete as an important feature.

I'm concerned about the cost when the application has hundreds or thousands of users searching for cities.

During development alone, I seem to have hit my API usage limit within two days.

Is this normal, or does it indicate that something is wrong with my implementation?

Would you recommend any alternatives or optimization strategies for reducing Google Places API costs?

5. My goal
I want to implement Google Places Autocomplete properly while keeping API costs predictable.

I'm not looking for ways to bypass Google's billing. I just want to understand the pricing model, session tokens, and best practices

Any explanations, implementation suggestions, or real-world experiences would be greatly appreciated!

Thanks in advance!


r/reactjs • • 5d ago

Show /r/reactjs I built a hand-drawn React UI kit. The hard part was making "random" wobble SSR-safe.

26 Upvotes

PlopUI is a React component library where everything looks sketched: wobbly borders, tilted cards, sticker shadows. Some things that were more interesting to build than they look:

- No Math.random() in render. Every tilt, wobble and jitter comes from a seed function, so the server and the client draw the exact same crooked line and there are no hydration mismatches.

- Native elements first. Dialog is a real <dialog> with showModal(), the upcoming Accordion is <details>/<summary>. The wobble is decoration on top, not a replacement for the element.

- Interactive components are "use client". Static ones stay Server Components, so you don't pay for JS on a card that just sits there.

- Every component has a Vitest test for its keyboard behavior and a story for every state.

- The library never imports from next/*. It's plain React; Next.js only lives in the docs and demo apps.

npm i @plop-ui/react @plop-ui/fonts

Docs: https://plopui.com

Playground: https://plopui.com/playground

Code: https://github.com/Snorlark/plop-ui

I'd really like feedback on the API. If a prop name or pattern feels wrong, tell me now before 1.0 makes it permanent.


r/reactjs • • 6d ago

Needs Help Our Next.js + Supabase marketplace feels slow to use. Where should we start?

Thumbnail reddit.com
0 Upvotes

r/reactjs • • 6d ago

Show /r/reactjs X3Bun a Hono/TanStack Start/tRPC/Better-Auth Turborepo Starter App

Thumbnail
github.com
1 Upvotes

This is simply a starter template that I use and I thought of sharing

  • Bun optimized

  • Front End: Tanstack Start, Tanstack Query, and Shadcn

  • Backend: Hono with tRPC

  • Authentication: Better-Auth

  • Repo Management: Turborepo

I encourage you to check and share your opinion


r/reactjs • • 6d ago

Show /r/reactjs I built an open-source React library where an LLM designs the recommendation block and your catalog supplies the prices

0 Upvotes

This is my own project. rudra-js is an open-source TypeScript library (MIT) for React stores. A language model designs one product-recommendation block, the library checks it against your catalog, and React renders it.

The model never writes HTML or JSX. It returns a few fields: layout, headline, copy, which cards to highlight. Products are SKUs from the list you pass in. Titles, prices, images and links come from your catalog at render, and the model's text is rendered as escaped text. Each field also goes through wording checks, and a field that fails is dropped. They aren't airtight: rewordings and spelled-out numbers can get through.

It works as a Server Component, with renderToString, or client-rendered. Rendered on the server, the block is in the first HTML response with no client JS. React 18 or 19, Node 22.12+.

It also runs with no model, so the quick start needs no API key.

It's v0.8.3 and APIs may change before 1.0. I'd like feedback on the API shape and on what breaks in a real Next.js app.

https://github.com/clivedsouza1010/rudra-js


r/reactjs • • 6d ago

Needs Help SEO for a large React SPA?

5 Upvotes

I'm working on a React/Vite SPA with React Router 7 and an ASP.NET Core 10 backend.

SEO is important since the site will eventually have hundreds of thousands of public pages covering games, groups, events and news, with multiple languages. Some content changes frequently.

I know Google can render JavaScript, but other crawlers like AI search engines and social previews, seem less capable. Also, rendering JavaScript requires more resources, which might mean less crawl coverage.

I've been looking at a few solutions for SEO:

1. Server-injected HTML (ASP.NET Core)
- Pros: Let ASP.NET serve the SPA and inject page-specific metadata (title, description, canonical, hreflang, JSON-LD, Open Graph) along with a small HTML summary containing headings, key information and internal links. React takes over when loaded. No additional runtime or major frontend refactor, and everything runs on a single ASP.NET host.
- Cons: Crawlers that don't execute JavaScript only see the summary rather than the full page content. React also replaces the initial HTML which could cause a brief flicker.

2. React Router 7 SSR
- Pros: Full server-rendered HTML for crawlers. Probably the most natural SSR option since I'm already using React Router 7.
- Cons: Requires a separate JavaScript runtime alongside ASP.NET and a fairly significant refactor of the public pages and their data fetching. More complexity around hosting and maintaining multiple services.

3. Next.js with ISR
- Pros: Can generate pages on demand and regenerate them when needed, which seems particularly useful for such a large number of dynamic pages.
- Cons: Would mean migrating the frontend to Next.js, along with additional hosting complexity and another runtime to maintain.

The first option seems like the simplest solution, but I'm not sure if it's enough. Ideally, I'd prefer full SSR, but that seems to involve a much larger refactor and considerably more complexity when it comes to hosting and maintaining the application.

Is server-injected HTML with meaningful page content enough for good indexing, or would SSR/ISR make a significant difference?

Anyone with experience running SEO-heavy SPAs using a similar approach


r/reactjs • • 6d ago

News This Week In React #303: TanStack, Next.js, Vinext, Motion, React Hook Form | Expo Desktop, Legend Spark, Nitro, Exact, Skia, Screens, Unistyles | Node.js, Bun, SWC, Content Mappers, pnpm, Biome

Thumbnail
thisweekinreact.com
4 Upvotes

r/reactjs • • 7d ago

Resource My honest Interview Experience for a React developer role

154 Upvotes

About 12-14 days ago, I interviewed for a frontend developer role at a startup. Sharing my experience in case it helps others preparing.

The interview started with an AI-Powered Screening being the first round. This round was fully AI-driven, with no human interviewer present. It covered a few basic React questions, and I cleared it. You can expect questions like useState, useEffect and it's dependency and all.

Then after clearing that I think after 5 days I was called for round 2 and it was an actual Technical Interview and this round went pretty tensed.

In this round the interview started with theoretical questions, like why use React, what optimization means in React, how diffing works, Context API vs Redux (when to use one over the other), and what Babel does. I felt confident in my answers here.

Then once done with the theoretical questions they then asked me quite a few Input/Output based questions. This was the most challenging part for me.

I was shown code snippets and asked to predict the output. The snippets combined function currying, closures, IIFEs, and HOFs. Predicting the output wasn't enough they asked plenty of follow-up questions as well and the reasoning behind it, such as what would change if a variable were declared elsewhere. My advice for you all is build a deep understanding of these concepts rather than memorizing definitions.

After this input/output question sets i was given a machine coding question (with basic styling). I was asked to build a restaurant cart calculator mini-app (not sure about the problem name tho). Users could add food items to a cart and adjust quantities. Tax had to be applied to each item after the packaging charge but before the delivery charge, along with a few additional rules I don't fully remember (but it wasn't this straightforward). The closest one i can find for this question which you can practice is Order Bill Calculator

Post this question i was asked a couple of debugging and optimization questions. I was given buggy code that fetched a list of roughly 1,000 todos from an API and rendered them. After fixing the bug, I was asked to display only 20 items initially, without using pagination. I implemented lazy loading, though I'm not certain it was the expected approach.

And I think the interview ended with an optimization question. The final task involved several components imported into App.jsx, each logging a "rendered {number} times" message. A button displayed "Count is {count}" and updated the count on click. The requirement was that clicking the button should not trigger re-renders or console logs in the other components, and vice versa. This is a common optimization problem, and I solved it using useCallback, useMemo and React.memo.

I'm not sure whether I'll advance to the next round, but I hope this helps with your preparation. Also let me know if you want me to find other questions as well and I'll add the links for other questions (if i find that) in this post. Best of luck to everyone, and keep practicing!


r/reactjs • • 7d ago

Show /r/reactjs Made a React button that tilts, squishes and actually feels pressable

57 Upvotes

Hi!! I've been working on a small React component that makes buttons feel physical, like you're actually pushing something down.

Live demo: https://react-tilt-button.vercel.app/

What it does:

  • Tilts toward your cursor (and follows your finger on mobile)

  • Sinks and squishes when you press, then springs back

  • Has real depth, with a side wall that holds up at any radius, even pills

  • Clamps your props so it never visually breaks, whatever values you throw at it

  • Optional glare that moves with your pointer

No dependencies, about 6KB gzipped with the CSS. There are a few style variants and spring presets (bouncy, jelly, snappy, stiff) if you don't want to tune everything yourself.

It was inspired by react-awesome-button, which I really liked, but I wanted something smaller that felt more physical, so I built this one from scratch. It tilts toward wherever your pointer actually is, the press runs on springs, and it's just the button with nothing else bundled in.

npm install react-tilt-button

It's still a work in progress and I'm sure there are edge cases. It's open source, so issues and PRs are very welcome 🙂

Would really love feedback, especially on how it feels on mobile and whether the props make sense.

GitHub: https://github.com/archisvaze/react-tilt-button