What is Reactive?
⚛️ Reactive is a state management library for JavaScript applications, offering many features that make it both easy to use and powerful.
- 🧩 Flexible to use: Want to change store state? Just mutate it anywhere you want.
- 😊 User-Friendly: Cover over 80% of the use cases with create method.
- ⚡️ Optimized Performance: Leverages Proxy API to provide the best performance.
- 🏄 Unopinionated: Works well both in React and Vanilla JS.
- 🦄 TypeScript Support: Written in TypeScript, fully typed, better DX.
- 🛠️ DevTools Integration: Out-of-the-box Redux DevTools compatibility.
Head over to the installation section to get started.
Try it Online
You can try Reactive online on CodeSandbox.
Example of React
Here is a simple example of using Reactive in a React application.
import { create } from '@shined/reactive'
const store = create({ count: 1 })
function App() {
const count = store.useSnapshot((s) => s.count)
return (
<div>
<p>Count is {count}</p>
<button onClick={() => store.mutate.count++}>increment</button>
</div>
)
}
For more information, see React Usage or API Reference.
Mutate Freely, Consume Safely
Reactive adopts a read-write separation approach, offering a straightforward way to mutate the state through the store.mutate
object. When you need to change the state, simply alter it!
export function increment() {
store.mutate.count++
}
export function updateUserInfo() {
store.mutate.user.info = { name: 'Alice' }
}
For consumption, it provide a simple method of accessing state via useSnapshot()
in React and getSnapshot()
in Vanilla JS to ensure security. This approach generates non-extensible snapshot states to prevent accidental modifications.
// in React component
const count = store.useSnapshot((s) => s.count)
const { count } = store.useSnapshot()
// in vanilla JS/TS
import { getSnapshot } from '@shined/reactive/vanilla'
const { count } = getSnapshot(store.mutate)
Optional Render Optimization
Furthermore, Reactive provides an optional render optimization feature.
// only re-render when `count` changes
const count = store.useSnapshot((s) => s.count)
You can use selector
to specify the state you want to listen to, which will only re-render when the specified state changes. By default, component that has used whole snapshot will trigger a re-render when any part of the state changes if you don't specify the selector
.
Click to see example
import { create } from '@shined/reactive'
const store = create({
name: 'Bob',
age: 18,
hobbies: ['swimming', 'running'],
address: {
city: {
name: 'New York',
},
},
})
function App() {
// re-render when ANY part of the state changes
const state = store.useSnapshot()
// only re-render when `city` object changes
const { name: cityName } = store.useSnapshot((s) => s.address.city)
// only re-render when `hobbies` object changes
const [hobby1, hobby2] = store.useSnapshot((s) => s.hobbies)
// only re-render when `name` changes
const name = store.useSnapshot((s) => s.name)
return <div>{name}</div>
}
export default App