Vaultrice React SDK - v1.1.0
    Preparing search index...

    Vaultrice React SDK - v1.1.0

    Vaultrice React SDK

    npm version

    A set of React hooks and utilities for building real-time, offline-first, and optionally end-to-end encrypted applications using Vaultrice NonLocalStorage.
    Under the hood, @vaultrice/react uses @vaultrice/sdk for all storage, sync, and presence features.

    Vaultrice is ideal for collaborative apps, cross-device sync, and privacy-sensitive use cases—without custom backend infrastructure.


    1. Features
    2. Installation
    3. Quick Start
    4. Core Hooks
    5. Atomic Operations
    6. Examples
    7. Helpers
    8. Related Packages

    • Offline-first: Local queueing and automatic sync when online.
    • Real-time presence & messaging: Built-in WebSocket support for live updates and user presence.
    • End-to-end encryption: Optional client-side encryption for sensitive data.
    • Cross-device sync: Seamless state sharing across browsers and devices.
    • TTL & metadata: Per-key expiration and rich metadata.
    • Atomic operations: Server-side atomic operations for counters, arrays, and objects.
    • Easy integration: Simple React hooks for state, counters, messaging, and more.

    npm install @vaultrice/react
    

    import { useNonLocalState } from '@vaultrice/react'

    const [value, setValue, error] = useNonLocalState<string>('myRoom', 'myKey', {
    credentials: {
    projectId: 'YOUR_PROJECT_ID',
    apiKey: 'YOUR_API_KEY',
    apiSecret: 'YOUR_API_SECRET'
    }
    })

    // Use value in your UI, update with setValue(newValue)

    • useNonLocalState – Manage a single value with real-time sync.
    • useMultiNonLocalStates – Manage multiple keys atomically.
    • useNonLocalCounter – Atomic increment/decrement for counters.
    • useNonLocalArray – Array management with atomic push and splice operations.
    • useNonLocalObject – Object management with merge and nested operations.
    • useNonLocalGeneralState – General state with all atomic operations available.
    • useMessaging – Real-time messaging and presence.
    • createNonLocalStore – Simple fetch/post API for a single key, e.g., to be used with TanStack Query.

    The SDK provides powerful atomic operations that are executed server-side, preventing race conditions:

    import { useNonLocalCounter } from '@vaultrice/react'

    const [count, increment, decrement, error] = useNonLocalCounter('roomId', 'counterKey', {
    credentials: { ... }
    })

    // Increment by 1 (default)
    await increment()

    // Increment by specific amount
    await increment(5)

    // Decrement by 1 (default)
    await decrement()

    // Decrement by specific amount
    await decrement(2)
    import { useNonLocalArray } from '@vaultrice/react'

    const [items, { push, splice, setArray }, error] = useNonLocalArray('roomId', 'listKey', {
    credentials: { ... }
    })

    // Atomically append to array
    await push('new item')

    // Splice examples — atomically remove/insert/replace elements:
    // Remove 1 item at index 2
    await splice(2, 1)

    // Insert items at index 1 without deleting
    await splice(1, 0, ['inserted'])

    // Replace 2 items starting at index 0 with new items
    await splice(0, 2, ['a', 'b'])

    // Replace entire array
    await setArray(['item1', 'item2', 'item3'])
    import { useNonLocalObject } from '@vaultrice/react'

    const [user, { merge, setIn, setObject }, error] = useNonLocalObject('roomId', 'userKey', {
    credentials: { ... }
    })

    // Shallow merge into object
    await merge({ name: 'John', active: true })

    // Set nested value using dot notation
    await setIn('profile.avatar', 'avatar.jpg')

    // Replace entire object
    await setObject({ name: 'John', age: 30 })
    import { useNonLocalGeneralState } from '@vaultrice/react'

    const [value, actions, error] = useNonLocalGeneralState('roomId', 'dataKey', {
    credentials: { ... }
    })

    // All operations available
    await actions.setItem(value)
    await actions.push(element) // for arrays
    // Splice via the general actions API (startIndex, deleteCount, items?)
    await actions.splice(1, 0, [newItem]) // insert newItem at index 1
    await actions.splice(3, 2) // remove 2 items starting at index 3
    await actions.merge(obj) // for objects
    await actions.setIn(path, value) // for nested objects

    import { useNonLocalCounter } from '@vaultrice/react'

    function CollaborativeCounter() {
    const [count, increment, decrement, error] = useNonLocalCounter('room1', 'counter', {
    credentials: {
    projectId: 'YOUR_PROJECT_ID',
    apiKey: 'YOUR_API_KEY',
    apiSecret: 'YOUR_API_SECRET'
    }
    })

    return (
    <div>
    <button onClick={() => increment()}>+1</button>
    <span>Count: {count}</span>
    <button onClick={() => decrement()}>-1</button>
    {error && <p>Error: {error.message}</p>}
    </div>
    )
    }
    import { useNonLocalArray } from '@vaultrice/react'

    function TodoList() {
    const [todos, { push, splice }, error] = useNonLocalArray('room1', 'todos', {
    credentials: { ... }
    })

    const addTodo = (text: string) => {
    push({ id: Date.now(), text, completed: false })
    }

    return (
    <div>
    <ul>
    {todos.map(todo => (
    <li key={todo.id}>{todo.text}</li>
    ))}
    </ul>
    <button onClick={() => addTodo('New task')}>Add Todo</button>
    </div>
    )
    }
    import { useNonLocalObject } from '@vaultrice/react'

    function UserProfile() {
    const [profile, { merge, setIn }, error] = useNonLocalObject('user123', 'profile', {
    credentials: { ... }
    })

    const updateEmail = (email: string) => {
    merge({ email })
    }

    const updateProfilePicture = (url: string) => {
    setIn('profile.avatar', url)
    }

    return (
    <div>
    <h2>{profile.name}</h2>
    <p>Email: {profile.email}</p>
    <button onClick={() => updateEmail('new@email.com')}>
    Update Email
    </button>
    </div>
    )
    }
    import { useMessaging } from '@vaultrice/react'

    function ChatRoom() {
    const [connected, send, join, leave, getConnectionId, error] = useMessaging(
    'chatroom1',
    (message) => {
    console.log('Received:', message)
    },
    { credentials: { ... } }
    )

    useEffect(() => {
    join({ name: 'User123', avatar: 'avatar.jpg' })
    return () => leave()
    }, [])

    return (
    <div>
    <div>Connected users: {connected.length}</div>
    <button onClick={() => send({ text: 'Hello!', timestamp: Date.now() })}>
    Send Message
    </button>
    </div>
    )
    }
    import { createNonLocalStore } from '@vaultrice/react'
    import { useQuery, useMutation } from '@tanstack/react-query'

    const userStore = createNonLocalStore('users', 'current-user', {
    credentials: { ... }
    })

    function UserData() {
    const { data: user, isLoading } = useQuery({
    queryKey: ['user'],
    queryFn: userStore.fetch
    })

    const updateUser = useMutation({
    mutationFn: userStore.post
    })

    return (
    <div>
    {isLoading ? 'Loading...' : user?.value?.name}
    <button onClick={() => updateUser.mutate({ name: 'New Name' })}>
    Update
    </button>
    </div>
    )
    }

    You can initialize your credentials in a single place to be reused:

    // e.g., in your index.ts
    import { vaultrice } from '@vaultrice/react'

    vaultrice.init({
    projectId: 'YOUR_PROJECT_ID',
    apiKey: 'YOUR_API_KEY',
    apiSecret: 'YOUR_API_SECRET'
    })

    // in your components - credentials are automatically used
    import { useNonLocalState } from '@vaultrice/react'

    const [value, setValue] = useNonLocalState<string>('objectId', 'myKey')

    To take advantage of the offline-capable NonLocalStorage, prepare the instances before usage:

    // e.g., in your index.ts
    import { prepareOfflineNonLocalStorage } from '@vaultrice/react'

    await prepareOfflineNonLocalStorage('objectId', credentials)

    // in your components - it will automatically use the prepared offline variant
    import { useNonLocalState } from '@vaultrice/react'

    const [value, setValue] = useNonLocalState<string>('objectId', 'myKey')

    const [value, setValue, error, isLoading] = useNonLocalState<T>(id, key, options)
    
    const [count, increment, decrement, error, isLoading] = useNonLocalCounter(id, key, options)
    
    const [array, { push, splice, setArray }, error, isLoading] = useNonLocalArray<T>(id, key, options)
    
    const [object, { merge, setIn, setObject }, error, isLoading] = useNonLocalObject<T>(id, key, options)
    
    const [value, { setItem, push, splice, merge, setIn }, error, isLoading] = useNonLocalGeneralState<T>(id, key, options)
    
    const [values, setItems, error, isLoading] = useMultiNonLocalStates(id, keys, options)
    
    const [connected, send, join, leave, getConnectionId, error] = useMessaging(id, onMessage, options)
    

    Have questions, ideas or feedback? Open an issue or email us at support@vaultrice.com


    Made with ❤️ for developers who need real-time storage, without the backend hassle.

    Try Vaultrice for free!