particule
Fine-grained atomic React state management library
yarn add particule
Particule is an atomic React state management library inspired by the best of Recoil, Jotai and Redux. You can choose which component subscribe to which state and so avoid useless re-render and computations.
✨ Features
- Super-easy API
- TypeScript ready
- Suspense support
- Minimal footprint (1kB gzipped)
- Hooks to add functionality
🚀 Examples
Basic
const textAtom = atom('Hello world!')
function App() {
const [text, setText] = useAtom(textAtom)
return (
<>
<p>{text}</p>
<button onClick={() => setText('Updated!')}>Update</button>
</>
)
}
Fine-grained
const textAtom = atom('Hello world!')
function Text() {
const text = useGetAtom(textAtom)
return <p>{text}</p>
}
// Won't re-render!
function Button() {
const setText = useSetAtom(textAtom)
return <button onClick={() => setText('Updated!')}>Update</button>
}
// Won't re-render!
function App() {
return (
<>
<Text />
<Button />
</>
)
}
Composition
const eurosAtom = atom(10)
const dollarsAtom = atom(get => get(eurosAtom) * 1.15)
function App() {
const [euros, setEuros] = useAtom(eurosAtom)
const [dollars, setDollars] = useAtom(dollarsAtom)
return (
<>
<input onChange={({ target }) => setEuros(target.value)} value={euros} />
<input onChange={({ target }) => setDollars(target.value)} value={dollars} />
</>
)
}
Suspense
const nameAtom = atom(async () => {
const json = await (await fetch("https://randomuser.me/api/")).json();
return json.results[0].name.first;
});
function Name() {
const name = useGetAtom(nameAtom)
return <p>My name is {name}</p>
}
function App() {
return (
<Suspense fallback='Loading...'>
<Name />
</Suspense>
)
}
Dispatch
const counterAtom = atom(0)
const dispatchCounter = dispatch(counterAtom, value => ({
increment: (newValue: number) => value + newValue,
decrement: (newValue: number) => value - newValue,
}))
function App() {
const counter = useGetAtom(counterAtom)
return (
<>
<p>{counter}</p>
<button onClick={() => dispatchCounter('increment', 1)}>Increment</button>
<button onClick={() => dispatchCounter('decrement', 1)}>Decrement</button>
</>
)
}
Custom atom
with hooks
const noZeroAtom = createAtom({
beforeValueSet: (_, value) => {
if (value === 0) {
throw new Error('Cannot set value to 0')
}
return value
}
})
const counterAtom = noZeroAtom(3)
function App() {
const [count, setCount] = useAtom(counterAtom)
return (
<>
<p>{count}</p>
<button onClick={() => setCount(count => count - 1)}>Reduce</button>
</>
)
}