A universal and lightweight state management library with a clean, stateless API.
# Universal
npm install @neabyte/stateless-js
# Angular (Automatic Reactivity)
npm install @neabyte/stateless-js @angular/core
# React (Automatic Re-renders)
npm install @neabyte/stateless-js react
# Svelte (Automatic Reactivity)
npm install @neabyte/stateless-js svelte
# Vue (Automatic Reactivity)
npm install @neabyte/stateless-js vue
// CommonJS
const { createStateless, useStateless } = require('@neabyte/stateless-js')
// ESM (ES Modules)
import { createStateless, useStateless } from '@neabyte/stateless-js'
// Angular (Automatic Reactivity)
import { StatelessService, useAngularStateless } from '@neabyte/stateless-js/angular'
// React (Automatic Re-renders)
import { useReactStateless } from '@neabyte/stateless-js/react'
// Svelte (Automatic Reactivity)
import { useSvelteStateless } from '@neabyte/stateless-js/svelte'
// Vue (Automatic Reactivity)
import { useVueStateless } from '@neabyte/stateless-js/vue'
// TypeScript types
import type { StateSetter, StateValue } from '@neabyte/stateless-js'
// CDN
<script src="https://unpkg.com/@neabyte/stateless-js/dist/index.mjs"></script>
// jsDelivr ESM
<script type="module">
import { createStateless, useStateless } from 'https://cdn.jsdelivr.net/npm/@neabyte/stateless-js/dist/index.mjs'
</script>
import { createStateless, useStateless } from '@neabyte/stateless-js'
// Create a new state
const [setCount, count] = createStateless('counter', 0)
console.log(count.value) // 0
// Update state
setCount(current => current + 1)
console.log(count.value) // 1
import { StatelessService, useAngularStateless } from '@neabyte/stateless-js/angular'
// Using the service approach
@Injectable({ providedIn: 'root' })
export class MyService {
constructor(private stateless: StatelessService) {}
counterState = this.stateless.useAngularStateless('counter', 0)
count = this.counterState[1]
setCount = this.counterState[0]
}
// Using the standalone function approach
export class MyComponent {
counterState = useAngularStateless('counter', 0)
count = this.counterState[1]
setCount = this.counterState[0]
increment = () => this.setCount(current => current + 1)
}
// In your Angular component
@Component({
template: `
<div>
<p>Count: {{ count() }}</p>
<button (click)="increment()">Increment</button>
</div>
`
})
export class CounterComponent {
counterState = useAngularStateless('counter', 0)
count = this.counterState[1]
setCount = this.counterState[0]
increment = () => this.setCount(current => current + 1)
}
import { useReactStateless } from '@neabyte/stateless-js/react'
function Counter() {
const [setCount, count] = useReactStateless('counter', 0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
</div>
)
}
import { useSvelteStateless } from '@neabyte/stateless-js/svelte'
// In your Svelte component
const [setCount, count] = useSvelteStateless('counter', 0)
const increment = () => setCount(current => current + 1)
<!-- In your .svelte file -->
<script>
import { useSvelteStateless } from '@neabyte/stateless-js/svelte'
const [setCount, count] = useSvelteStateless('counter', 0)
const increment = () => setCount(current => current + 1)
</script>
<div>
<p>Count: {$count}</p>
<button on:click={increment}>Increment</button>
</div>
import { useVueStateless } from '@neabyte/stateless-js/vue'
export default {
name: 'Counter',
setup() {
const [setCount, countValue] = useVueStateless('counter', 0)
const count = computed(() => countValue.value)
const increment = () => {
setCount(current => current + 1)
}
return {
count,
increment
}
}
}
// Universal
const [setUser, user] = createStateless('user', { name: 'John', age: 25 })
const [setUser2, user2] = useStateless('user', { name: 'Default', age: 0 })
console.log(user.value === user2.value) // true - same state
// React - Multiple components share the same state
function UserProfile() {
const [setUser, user] = useReactStateless('user', { name: 'John', age: 25 })
return <div>Name: {user.name}, Age: {user.age}</div>
}
function UserEditor() {
const [setUser, user] = useReactStateless('user', { name: 'Default', age: 0 })
return <button onClick={() => setUser(u => ({ ...u, age: u.age + 1 }))}>
Increase Age
</button>
}
// Vue - Multiple components share the same state
export default {
name: 'UserProfile',
setup() {
const [setUser, userValue] = useVueStateless('user', { name: 'John', age: 25 })
const user = computed(() => userValue.value)
return { user }
}
}
export default {
name: 'UserEditor',
setup() {
const [setUser, userValue] = useVueStateless('user', { name: 'Default', age: 0 })
const user = computed(() => userValue.value)
const increaseAge = () => {
setUser(u => ({ ...u, age: u.age + 1 }))
}
return { user, increaseAge }
}
}
// Numbers
const [setNum, num] = createStateless('number', 42)
// Strings
const [setStr, str] = createStateless('string', 'hello')
// Objects
const [setObj, obj] = createStateless('object', { count: 0, items: [] })
// Arrays
const [setArr, arr] = createStateless('array', [1, 2, 3])
// Special values
const [setNaN, nan] = createStateless('nan', NaN)
const [setInf, inf] = createStateless('infinity', Infinity)
const [setSymbol, sym] = createStateless('symbol', Symbol('test'))
const [setBigInt, big] = createStateless('bigint', BigInt(123))
// Universal
const [setData, data] = createStateless('data', { count: 0, items: [] })
// React
const [setData, data] = useReactStateless('react-data', { count: 0, items: [] })
// Vue
const [setData, dataRef] = useVueStateless('vue-data', { count: 0, items: [] })
const data = computed(() => dataRef.value)
// Immutable updates work the same way
setData(current => ({ ...current, count: current.count + 1 }))
setData(current => ({ ...current, items: [...current.items, 'new item'] }))
const [setTemp, temp] = createStateless('temporary', 'data')
// Use the state...
console.log(temp.value)
// Clean up when done
temp.dispose()
// Accessing disposed state throws error
try {
console.log(temp.value) // Error: State has been disposed
} catch (error) {
console.log(error.message)
}
Creates a new state with the given ID and initial value.
id
: Unique identifier (string or number)initialState
: Initial value for the state- Returns: Tuple
[StateSetter<T>, StateValue<T>]
Uses existing state if it exists, otherwise creates a new one.
id
: Unique identifier (string or number)fallbackState
: Value to use if state doesn't exist- Returns: Tuple
[StateSetter<T>, StateValue<T>]
Angular service method that provides automatic reactivity using Angular signals.
id
: Unique identifier (string or number)initialValue
: Initial value for the state- Returns: Tuple
[StateSetter<T>, Signal<T>]
(Angular signal for reactivity)
Standalone Angular function that provides automatic reactivity using Angular signals.
id
: Unique identifier (string or number)initialValue
: Initial value for the state- Returns: Tuple
[StateSetter<T>, Signal<T>]
(Angular signal for reactivity)
React hook that provides automatic re-renders when state changes.
id
: Unique identifier (string or number)initialValue
: Initial value for the state- Returns: Tuple
[StateSetter<T>, T]
(direct value, not StateValue object)
Svelte function that provides automatic reactivity using Svelte stores.
id
: Unique identifier (string or number)initialValue
: Initial value for the state- Returns: Tuple
[StateSetter<T>, Writable<T>]
(Svelte writable store for reactivity)
Vue composable that provides automatic reactivity when state changes.
id
: Unique identifier (string or number)initialValue
: Initial value for the state- Returns: Tuple
[StateSetter<T>, Ref<T>]
(reactive ref for Vue reactivity)
Function to update state: (updater: StateUpdater<T>) => void
Object with:
value
: Current state value (readonly)dispose()
: Method to clean up the state
This project is licensed under the MIT license. See the LICENSE file for more info.