Open-source project
kristiandupont/react-geiger avatar
kristiandupont/react-geiger

react-geiger: hear your slow React re-renders as clicks

Audiolize React performance

1,103 stars7 forksTypeScriptMIT

At a glance

What is it?
react-geiger is a small TypeScript package that wraps part of your tree in a component and plays a click whenever a re-render takes longer than a threshold, turning a performance problem into an audible cue. It suits a developer who wants to notice jank without watching a flame chart, and it relies on React.Profiler, which is off in production builds, so it is a development tool rather than a monitoring one.
Who is it for?
react-geiger suits a React developer who is chasing unexplained re-renders and wants a peripheral signal rather than a profiling session, and it is easy to drop into an existing tree because the API is one wrapper component.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A click instead of a flame chart

The idea behind react-geiger is audiolizing. The package is described as a tool for audiolizing React performance issues, and the mechanism is deliberately physical rather than analytical. You leave it running in the background and it makes little clicks, and those clicks point your attention to excessive, slow component re-renders. The inspiration is the Geiger counter metaphor, and the README includes a photograph captioned Not Great, Not Terrible.

The value of this approach is that it works when the profiling tools do not. A flame chart is a snapshot of one render at a time, and it tells you what happened once. A click tells you that something happened, repeatedly, while you were using the application, and it does so through a different sensory channel than the screen. When you are working on a feature and the browser is being sluggish in a way you cannot articulate, hearing an irregular click pattern is a different kind of evidence from seeing a spinner.

The package is tiny in scope. The repository contains src/, a package.json, a tsconfig, an eslint config, a renovate configuration, a logo image and the license file. There is no application, no service and no configuration file to write, and no GitHub releases. The published version is 1.2.2, the main entry point is dist/index.js with the type declarations at dist/index.d.ts, and the build is a plain tsc invocation. The peer dependency range is generous, covering React 16.8 through 19, which tells you the author intends it to drop into an existing project rather than shape one.

The Geiger wrapper and its five options

The usage model is one component. You wrap whatever you want to track in a Geiger component, and re-renders inside it cause a click if they take longer than the threshold. The most basic setup wraps the entire application.

tsx
<Geiger>
  <App />
</Geiger>

You can also apply it to a sub-tree, which is the more useful form once you know where the problem is. The options are a small, focused set.

tsx
  profilerId?: string;
  renderTimeThreshold?: number;
  phaseOption?: PhaseOption;
  customSoundFile?: string
  enabled?: boolean;

The renderTimeThreshold is the time in milliseconds that triggers a click, and the default is 50. Setting it to 0 makes any re-render click, which is the mode to use while you narrow a problem down and the mode to leave once you have found it. The phaseOption chooses which render phase you care about, and it takes mount, update or both, with both as the default. The customSoundFile option takes a path to a sound file if the default click is not what you want to hear. The profilerId is passed through to the React.Profiler component, and the documentation is candid that you probably do not need to change it. The enabled option defaults to true and lets you turn the whole thing off.

That last option carries the most important caveat in the README, and it is worth reading twice. The tool relies on React.Profiler under the hood, and React disables the profiler in production builds by default. So the instrument is available in development and absent in production, which is what makes this a development instrument rather than a monitoring one.

A package with no tests and a licence mismatch

Two things in the package manifest are worth reading before you depend on this. The first is the test script, which is set to echo an error message and exit with a failure, the standard placeholder that ships with npm init. There is no test suite in the repository and no test/ directory, and the repository listing confirms it, with no test folder among the top level entries. The lint script is real, running eslint over the TypeScript and TSX files with the visualstudio formatter and the unused disable directives report enabled, and the build script is a tsc compile, so the code is type checked and linted even though it is not tested. For a package whose entire surface is a wrapper and a threshold comparison, the absence of tests is a small gap rather than a large one, but it is a gap.

The second is the licence. The repository listing records the licence as MIT, while the package.json records the license field as ISC. Both are permissive, and both are short documents with a very different tone, ISC being closer to the BSD text. The MIT declaration also appears in the repository's LICENSE file. If you are shipping a product and need the terms to be unambiguous, the disagreement between the manifest and the file is exactly the kind of thing to raise with the author, and it costs a question to ask. The repository carries a renovate configuration, so dependency updates are automated, and the last push was on 2026-10-13, which means the package is being worked on even though nothing has been tagged as a release.

Where react-geiger is the wrong tool

Three cases argue against it. The first is production monitoring. The whole premise is that React.Profiler is disabled in production builds by default, so a click in a deployed application is not something you can rely on, and if you need to know which component is slow in production you need a different tool that reports numbers rather than sounds. The second is attribution. The click tells you that a slow render happened inside the Geiger boundary, not which component inside it was responsible, and the threshold applies to the wrapped tree. For a large application that is a coarse instrument, and the fix is to narrow the boundary, which is more work than opening a profiler. The third is a team that treats a development dependency as a monitoring strategy. The package has no persistence, no reporting and no aggregation, so there is nothing to look at after the fact; a click is a signal for the person sitting in front of the browser at that moment.

There is a broader point about the approach. Audiolizing is a way of making an invisible cost perceptible, and it works best when the thing being perceived is otherwise unmeasured. If your build already reports render timings in a dashboard, the click adds a channel but no new information. And a related caution applies to any sound-based instrumentation, which is that it draws on attention, so an instrument that is easy to forget about is also easy to mute and never think about again. The fact that this package is a single component with five options and no configuration file is its main virtue and its main limit. For what it does, it does it in the smallest possible way, and for anything beyond that you need something that reports numbers.

Editorial conclusion

react-geiger suits a React developer who is chasing unexplained re-renders and wants a peripheral signal rather than a profiling session, and it is easy to drop into an existing tree because the API is one wrapper component. It does not suit production monitoring, because it depends on React.Profiler and the documentation notes that the profiler is disabled in production builds by default, and it does not suit a team that wants attribution down to the component that caused the slow render. Before you rely on it, run it in a development build, set renderTimeThreshold to 0 to make every re-render audible while you narrow the problem down, and check the licence, since the package metadata records ISC while the repository listing records MIT.

Frequently asked questions

How do I install and use react-geiger?

Run npm i react-geiger, then wrap the part of the tree you want to track in the Geiger component, for example <Geiger><App /></Geiger>. Re-renders inside it produce a click when they exceed the threshold.

What is the default render time threshold in react-geiger?

The default is 50 milliseconds. Setting renderTimeThreshold to 0 makes any re-render click, and the phaseOption setting chooses between mount, update and both, with both as the default.

Does react-geiger work in production builds?

Not by default. The documentation notes that it relies on React.Profiler under the hood, and that the profiler is disabled in production builds by default, so the tool is a development instrument.

Which React versions does react-geiger support?

The peer dependency range covers React 16.8, 17, 18 and 19. The published package version is 1.2.2 and the package ships only its dist/ directory, with the entry point at dist/index.js and types at dist/index.d.ts.

Official sources

  1. Issues
  2. kristiandupont/react-geiger on GitHub
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kristiandupont-react-geiger.svg)](https://hysenlabs.com/projects/kristiandupont-react-geiger)

Was this useful?