What is Reactive?
⚛️ Reactive is a library that provides state management capabilities for JavaScript applications, intuitive, flexible, and written in TypeScript.
- 😊 Beginner-Friendly: Covered more than 80% of use cases with the create method.
 
- 🧩 Flexible Usage: Want to change the stored state? Just modify it anytime, anywhere through mutate.
 
- ⚡️ Performance Optimization: Utilizes the Proxy API to provide the best possible performance.
 
- 🏄 Framework Agnostic: Works well both in React and Vanilla JavaScript.
 
- 🦄 TypeScript Support: Written in TypeScript, fully typed for a better development experience.
 
- 🛠️ DevTools Integration: Out-of-the-box compatibility with Redux DevTools.
 
React Usage Example
Here's a simple example of using Reactive in a React application.
import { create } from '@shined/reactive'
const store = create({ count: 1 })
const addOne = () => store.mutate.count++
function App() {
  const count = store.useSnapshot((s) => s.count)
  return (
    <div>
      <p>Count is {count}</p>
      <button onClick={addOne}>Increase</button>
    </div>
  )
}
 
For more information, please refer to React Usage or API Reference.
Try It Online
You can try Reactive online on CodeSandbox.
Free Mutation, Safe Consumption
Reactive adopts a read-write separation strategy, offering a more intuitive way of changing states through the store.mutate object. Simply modify the store.mutate object when you need to change states!
export const store = create({
  count: 1,
  user: { name: 'Bob' }
})
export function increment() {
  store.mutate.count++
}
export function updateUser() {
  store.mutate.user = { name: 'Alice' }
}
 
For consumption, it provides a simple method to access the state through React's store.useSnapshot and the pure JavaScript/TypeScript's store.snapshot, ensuring safety. This method generates a non-expandable snapshot state to prevent accidental modifications.
// In React components
const { count } = store.useSnapshot()
const count = store.useSnapshot((s) => s.count)
// In Vanilla JavaScript/TypeScript
const { count } = store.snapshot()
const count = store.snapshot(s => s.count)
 
Optional Rendering Optimization
Moreover, Reactive also provides an optional rendering optimization feature.
// Only re-renders when `count` changes, `s => s.count` is the selector, used to pick the specified state.
const count = store.useSnapshot((s) => s.count)
 
You can use selector to specify the state you want to pick, which will only re-render when the specified state changes. By default, components using the full snapshot will trigger a re-render whenever any part of the state changes.
Hint
For the design of the selector API, and why the "automatic dependency collection" approach was abandoned, refer to proxy-compare's issue#65.
 
A more comprehensive example of selector:
import { create } from '@shined/reactive'
const store = create({
  name: 'Bob',
  age: 18,
  hobbies: ['Swimming', 'Running'],
  address: { city: { name: 'New York' } },
})
export default function App() {
  // Will trigger re-render when any part of the store changes
  const state = store.useSnapshot()
  // Only re-renders when the `city` object in store changes
  const { name: cityName } = store.useSnapshot((s) => s.address.city)
  // Only re-renders when the `hobbies` object and `age` property in store change
  const [hobbies, age] = store.useSnapshot((s) => [s.hobbies, s.age] as const)
  // Only re-renders when the `name` in store changes
  const name = store.useSnapshot((s) => s.name)
}