🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@bhammond/react-stateful

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bhammond/react-stateful

A Signal and Querystate backed React State management utility library.

latest
Source
npmnpm
Version
1.3.12
Version published
Maintainers
1
Created
Source

@bhammond/react-stateful

Framework-agnostic URL-synchronized state management with built-in state sharing between components. Uses signals to share state efficiently between components.

Features

  • 🔄 State sharing between components using signals
  • 🌐 URL synchronization with component state
  • 🧭 Browser navigation (back/forward) support
  • 🤝 Framework agnostic design
  • 📦 TypeScript included
  • 🪶 Small bundle size (~1KB)
  • 💪 No dependencies

Installation

npm install @bhammond/react-stateful

Requirements

  • React 16.8+

Basic Usage

import { useQueryState } from '@bhammond/react-stateful';

function SearchComponent() {
  const params = new URLSearchParams(window.location.search);
  const [query, setQuery] = useQueryState('q', params);

  return (
    <input
      value={query ?? ''}
      onChange={(e) => setQuery(e.target.value)}
      placeholder="Search..."
    />
  );
}

State Sharing Between Components

Components using the same key will share state through signals:

import { useQueryState } from '@bhammond/react-stateful';

function SearchInput({ params }) {
  const [query, setQuery] = useQueryState('q', params);
  return <input value={query ?? ''} onChange={e => setQuery(e.target.value)} />;
}

function SearchResults({ params }) {
  const [query] = useQueryState('q', params);
  return <div>Results for: {query}</div>;
}

function FilterStatus({ params }) {
  const [query] = useQueryState('q', params);
  return <div>Current filter: {query || 'None'}</div>;
}

function SearchPage() {
  const params = new URLSearchParams(window.location.search);
  return (
    <div>
      <SearchInput params={params} />
      <FilterStatus params={params} />
      <SearchResults params={params} />
    </div>
  );
}

Complex Objects

The hook works with complex objects and maintains type safety:

interface Filters {
  search: string;
  category: string;
  sortBy: string;
  page: number;
}

const DEFAULT_FILTERS: Filters = {
  search: '',
  category: 'all',
  sortBy: 'date',
  page: 1
};

function FilterPanel({ params }) {
  const [filters, setFilters] = useQueryState<Filters>('filters', params, DEFAULT_FILTERS);

  const updateFilter = (key: keyof Filters, value: Filters[keyof Filters]) => {
    setFilters(current => ({
      ...current,
      [key]: value,
      page: key === 'page' ? value : 1
    }));
  };

  return (
    <div>
      <input
        value={filters.search}
        onChange={e => updateFilter('search', e.target.value)}
      />
      <select
        value={filters.category}
        onChange={e => updateFilter('category', e.target.value)}
      >
        {/* options */}
      </select>
    </div>
  );
}

API Reference

useQueryState

function useQueryState<T = string>(
  name: string,
  params: ParamsInput,
  defaultValue?: T
): [T, (newValue: T | ((prev: T) => T)) => void]

Parameters

  • name: string - URL parameter key
  • params: ParamsInput - Either:
    • URLParamsLike: An object with a get(key: string): string | null method
    • RecordParams: An object with string or string array values
  • defaultValue?: T - Optional default value when parameter is not present

Returns

  • [value, setValue] - A tuple containing the current value and setter function

Framework Integration

React Router

import { useSearchParams } from 'react-router-dom';
import { useQueryState } from '@bhammond/react-stateful';

function SearchComponent() {
  const [searchParams] = useSearchParams();
  const [query, setQuery] = useQueryState('q', searchParams);

  return (
    <input
      value={query ?? ''}
      onChange={(e) => setQuery(e.target.value)}
    />
  );
}

Custom Implementation

class CustomParams implements URLParamsLike {
  private params: Map<string, string>;

  constructor() {
    this.params = new Map();
  }

  get(key: string): string | null {
    return this.params.get(key) ?? null;
  }

  set(key: string, value: string): void {
    this.params.set(key, value);
  }
}

function Component() {
  const params = new CustomParams();
  const [value, setValue] = useQueryState('key', params);
  // ...
}

TypeScript Support

Includes TypeScript definitions with full type inference support.

Performance

  • Signal-based state sharing
  • Selective component updates
  • Batched URL updates
  • Small bundle size
  • No external dependencies

Contributing

Contributions are welcome. Please feel free to submit a Pull Request.

License

MIT

Keywords

react

FAQs

Package last updated on 19 Dec 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts