constate

repository·main·Indexed 26 days ago

https://github.com/diegohaz/constate

A library for state management and value observation in React. It provides a factory function that lifts a custom hook's state into React Context, returning a Provider component and context hooks. It supports selectors to split state into multiple contexts, allowing components to subscribe to specific slices of state to prevent unnecessary re-renders.

Tokens
1.9K
Snippets
4
Records
8
Agent score
88%

What's inside constate

  1. Split state into multiple contexts using selectors

    main

    To prevent unnecessary re-renders, you can pass selector functions to constate. Each selector splits the original hook's value into a separate React Context. This allows components to subscribe only to the specific part of the state they need.

    Each selector function receives the value returned by useValue and returns the specific slice to be held by that context.

    const [Provider, useCount, useIncrement] = constate(
      useCounter,
      (value) => value.count,      // becomes useCount
      (value) => value.increment, // becomes useIncrement
    );
    import { useCallback, useState } from "react";
    import constate from "constate";
    
    function useCounter({ initialCount = 0 }) {
      const [count, setCount] = useState(initialCount);
      const increment = useCallback(() => setCount((prev) => prev + 1), []);
      return { count, increment };
    }
    
    // Split the values into separate hooks
    const [CounterProvider, useCount, useIncrement] = constate(
      useCounter,
      (value) => value.count, 
      (value) => value.increment,
    );
    
    function Button() {
      // This component only re-renders if increment changes (which it won't)
      const increment = useIncrement();
      return <button onClick={increment}>+</button>;
    }
    
    function Count() {
      // This component only re-renders when count changes
      const count = useCount();
      return <span>{count}</span>;
    }
    
    function App() {
      return (
        <CounterProvider initialCount={10}>
          <Count />
          <Button />
        </CounterProvider>
      );
    }
  2. Use the constate factory with a basic custom hook

    main

    To lift a custom hook's state into React Context, pass the hook to the constate factory. It returns a tuple containing a Provider component and a context hook.

    1. Define your custom hook.
    2. Wrap it with constate to get [Provider, useContextHook].
    3. Wrap your component tree with the Provider.
    4. Access the state using the returned hook in descendant components.
    import { useState } from "react";
    import constate from "constate";
    
    // 1️⃣ Create a custom hook as usual
    function useCounter() {
      const [count, setCount] = useState(0);
      const increment = () => setCount((prevCount) => prevCount + 1);
      return { count, increment };
    }
    
    // 2️⃣ Wrap your hook with the constate factory
    const [CounterProvider, useCounterContext] = constate(useCounter);
    
    function Button() {
      // 3️⃣ Use context instead of custom hook
      const { increment } = useCounterContext();
      return <button onClick={increment}>+</button>;
    }
    
    function Count() {
      // 4️⃣ Use context in other components
      const { count } = useCounterContext();
      return <span>{count}</span>;
    }
    
    function App() {
      // 5️⃣ Wrap your components with Provider
      return (
        <CounterProvider>
          <Count />
          <Button />
        </CounterProvider>
      );
    }
  3. constate(useValue[, ...selectors])

    main

    The primary API for constate. It is a factory method that converts a custom hook into a Provider and one or more context hooks.

    Parameters:

    • useValue: Any custom React hook. The hook can receive props, which will be passed to the returned <Provider />.
    • ...selectors (optional): One or more functions used to split the value returned by useValue into multiple contexts.

    Returns:

    • A tuple: [Provider, ...hooks].
      • Provider: A React component that wraps the tree and provides the state.
      • ...hooks: One hook for the full value (if no selectors are provided) or one hook per selector provided.

    Props: The returned Provider component accepts the same props as the original useValue hook.

  4. Configure oxfmt settings

    main

    Use defineConfig from oxfmt to configure formatting options. The configuration object supports controlling the line width and the behavior of import sorting.

    import { defineConfig } from "oxfmt";
    
    export default defineConfig({
      printWidth: 80,
      experimentalSortImports: {
        newlinesBetween: false,
      },
    });
  5. Use `constate` to manage lifted state

    main

    The constate function creates a React Provider and a set of specialized hooks to manage state. You provide a function useValue that computes the state based on props, and optionally provide selectors to slice the state into smaller, independent contexts. This prevents unnecessary re-renders in components that only consume a subset of the state.

    Return Value

    constate returns a tuple: [Provider, ...hooks].

    1. Provider: A React component that wraps your component tree. It accepts the same props as your useValue function.
    2. hooks:
      • If no selectors are provided: The first hook returns the full state value.
      • If selectors are provided: Each selector generates a corresponding hook. The hook returns the value returned by that specific selector function.
  6. Define selectors for `constate`

    main

    Selectors are functions used to partition the state into multiple contexts. Each selector function becomes a hook in the returned tuple.

    • Signature: (value: Value) => any
    • Behavior: When a selector is passed to constate, the Provider wraps the children in a new React.Context.Provider containing only the value returned by that selector. This allows components using the resulting hook to only re-render when that specific slice of state changes.
  7. Reference oxfmt configuration options

    main

    The following options are available in the defineConfig object:

    • printWidth: (number) Sets the maximum line length for formatted code.
    • experimentalSortImports: (object) Configures how imports are sorted.
      • newlinesBetween: (boolean) Determines whether newlines are inserted between import groups.