Gathering detailed insights and metrics for @reatom/preact
Gathering detailed insights and metrics for @reatom/preact
Gathering detailed insights and metrics for @reatom/preact
Gathering detailed insights and metrics for @reatom/preact
npm install @reatom/preact
Typescript
Module System
Node Version
NPM Version
primitives: v3.11.0
Updated on May 19, 2025
lens: v3.12.0
Updated on May 19, 2025
form: v3.4.0
Updated on May 19, 2025
devtools: v0.13.1
Updated on May 12, 2025
primitives: v3.10.0
Updated on May 12, 2025
persist-web-storage: v3.4.6
Updated on May 12, 2025
TypeScript (99.17%)
JavaScript (0.77%)
Shell (0.03%)
HTML (0.03%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1,201 Stars
2,795 Commits
122 Forks
20 Watchers
35 Branches
84 Contributors
Updated on Jul 10, 2025
Latest Version
1000.0.0-alpha.3
Package Id
@reatom/preact@1000.0.0-alpha.3
Unpacked Size
37.05 kB
Size
11.01 kB
File Count
8
NPM Version
10.9.2
Node Version
23.11.0
Published on
May 10, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
2
1
Reatom adapter for preact.
1npm i @reatom/preact
Read the handbook first for production usage.
Reatom offers powerful ways to integrate state management directly into your Preact components, ensuring reactivity and proper lifecycle management.
reatomComponent
The primary API to bind atoms and actions to a component's lifetime is reatomComponent
. It wraps your regular Preact component function, placing it within a Reatom reactive context.
Features:
myAtom()
) within the component function to read its value and subscribe to updates. The component will automatically re-render when the atom changes.useState
, useEffect
, etc.), accept props, and return any valid ReactNode
as usual.wrap()
(e.g., onClick={wrap(myAction)}
) to preserve the reactive context, especially for async operations or actions updating state.wrap
or implicitly by actions) are automatically aborted if the component unmounts before completion, preventing race conditions and memory leaks.1import { atom, wrap } from '@reatom/core' 2import { reatomComponent } from '@reatom/preact' 3 4export const page = atom(0, 'page').actions((target) => ({ 5 next: () => target((state) => state + 1), 6 prev: () => target((state) => Math.max(0, state - 1)), 7})) 8 9// Simple component reading and updating global state 10export const Paging = reatomComponent( 11 () => ( 12 <span> 13 <button onClick={wrap(page.prev)}>prev</button> {/* Use wrap */} 14 {page()} {/* Read atom value */} 15 <button onClick={wrap(page.next)}>next</button> {/* Use wrap */} 16 </span> 17 ), 18 'Paging', 19) // Naming the component is crucial for debugging! 20 21// Component accepting props (including atoms) 22type CounterProps = { 23 label: string 24 count: Atom<number> 25 increment: Action<[], number> 26} 27 28export const Counter = reatomComponent<CounterProps>( 29 ({ label, count, increment }) => ( 30 <div> 31 {label}: {count()} 32 <button onClick={wrap(increment)}> + </button> 33 </div> 34 ), 35 'Counter', 36) 37 38// Conditional rendering based on atom values 39export const SomeList = reatomComponent( 40 () => 41 isLoading() ? ( // Read atom conditionally 42 <span>Loading...</span> 43 ) : ( 44 <ul> 45 {list().map( 46 ( 47 el, // Read another atom 48 ) => ( 49 <li key={el.id}>{el.text}</li> 50 ), 51 )} 52 </ul> 53 ), 54 'SomeList', 55)
Do not forget to put the component name to the second argument, it will increase your feature debug experience a lot!
A key feature of reatomComponent
is its integration with Reatom's abort mechanism. When a reatomComponent
unmounts:
await wrap(fetch(...))
, await wrap(sleep(...))
) are automatically cancelled.effect
primitives created within its context are automatically cleaned up.This robust cleanup prevents common issues like trying to update state on unmounted components and avoids memory leaks from lingering subscriptions or timers. If you need an operation to survive component unmount (e.g., analytics), use spawn
from the core package.
reatomFactoryComponent
(Recommended for Local State/Effects)While reatomComponent
is great for reading atoms state, reatomFactoryComponent
is the recommended pattern for components that need their own local, encapsulated state and side effects.
It separates the component logic into two parts:
Benefits:
effect
: effect
primitives created in the factory are automatically cleaned up when the component unmounts, making it ideal for managing local subscriptions, timers, animations, etc.1import { atom, action, effect, wrap, sleep } from '@reatom/core' 2import { reatomFactoryComponent } from '@reatom/preact' 3 4// Example: A self-contained counter component 5const Counter = reatomFactoryComponent<{ initialCount: number; step?: number }>( 6 // 1. Factory Function (runs once per instance) 7 (initProps) => { 8 // Note that the props will not change in this initialization scope. 9 const step = initProps.step ?? 1 10 // Create local atom specific to this Counter instance 11 const count = atom(initProps.initialCount, 'localCount') 12 // Create local action 13 const increment = action(() => count((c) => c + step), 'increment') 14 const decrement = action(() => count((c) => c - step), 'decrement') 15 16 // Example: Log changes (effect cleans up automatically) 17 effect(() => { 18 const currentCount = count() 19 console.log(`Counter ${initProps.initialCount} changed to:`, currentCount) 20 // Cleanup function (optional, runs before next effect run or on unmount) 21 return () => 22 console.log( 23 `Counter ${initProps.initialCount} leaving state:`, 24 currentCount, 25 ) 26 }, 'logEffect') 27 28 // Return the render function 29 return (props) => ( 30 <div> 31 Count (Initial: {props.initialCount}, Step: {props.step ?? 1}):{' '} 32 {count()} 33 <button onClick={wrap(decrement)}>-</button> 34 <button onClick={wrap(increment)}>+</button> 35 </div> 36 ) 37 }, 38 'Counter', // Name the factory component! 39) 40 41// Usage: 42// <Counter initialCount={10} /> 43// <Counter initialCount={0} step={5} />
Example: Using effect
for Auto-Cleaning
reatomFactoryComponent
combined with effect
is excellent for managing resources that need cleanup. It is more powerful and precise primitive than useEffect
, as it isn't coupled with rerenders.
1import { atom, effect, wrap, sleep, isAbort } from '@reatom/core' 2import { reatomFactoryComponent } from '@reatom/preact' 3 4const IntervalLogger = reatomFactoryComponent<{ intervalMs: number }>( 5 ({ intervalMs }) => { 6 const tick = atom(0, 'tick') 7 8 // This effect runs a timer and cleans it up automatically on unmount 9 effect(async () => { 10 while (true) { 11 // sleep respects the abort context 12 await wrap(sleep(intervalMs)) 13 tick((t) => t + 1) 14 } 15 }, 'intervalEffect') 16 17 return (props) => ( 18 <div> 19 Interval ({props.intervalMs}ms) Ticks: {tick()} 20 </div> 21 ) 22 }, 23 'IntervalLogger', 24) 25 26// Usage: 27// <IntervalLogger intervalMs={1000} /> 28// When this component unmounts, the interval stops automatically.
reatomFactoryComponent
provides a robust and elegant way to build stateful, effectful components with automatic lifecycle management, leveraging the power of Reatom's core primitives like atom
and effect
.
Optionally, you need to set up the main context once and wrap your application in a provider at the top level. This is required if you have called clearStack()
(recommended).
1import { context, connectLogger, clearStack } from '@reatom/core' 2import { reatomContext } from '@reatom/preact' 3import { Main } from './path/to/an/Main' 4 5// Recommended: Disable default context for predictability 6clearStack() 7 8const rootFrame = context.start() 9if (import.meta.env.DEV) { 10 rootFrame.run(connectLogger) 11} 12 13export const App = () => ( 14 <reatomContext.Provider value={rootFrame}> 15 <Main /> 16 </reatomContext.Provider> 17)
No vulnerabilities found.
Reason
30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 5
Details
Reason
dangerous workflow patterns detected
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
Found 2/30 approved changesets -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More