Selector V2

A Redux-like system designed to optimize component rendering using Ariakit hooks.

Usage

createSelector creates a selector with a Provider and useSelector hook, enabling component-based state management.

Example

import { createSelector } from "swash/v2/utils/selector";

// `CountSelector` is private and should not be exposed directly.
const CountSelector = createSelector<CountStoreState>();

type CountStoreState = {
  count: number;
};

export const CountSelectorProvider = (props) => {
  const [count, setCount] = React.useState(0);
  // State cannot be `null`. Provide the entire state object; otherwise, selectors won't be able to listen for changes.
  return <ArticleSelector.Provider state={{ count }} {...props} />;
};

export const useCountSelector = CountSelector.useSelector;

useSelector Hook

useSelector selects state from the store, either by a key or a selector function. The signature is similar the Ariakit useStoreState hook.

Examples

Using a key:

const count = CustomSelector.useSelector("count");

Using a selector function:

const isEven = CustomSelector.useSelector((state) => state.count % 2 === 0);

unlike useStoreState, useSelector is designed for more granular selection:

const { id, title } = useArticleSelector((state) => ({
  id: state.id,
  title: state.title,
}));

The selector function is memoized and will only re-run when the selected state changes.

⚠️ Disclaimer

You cannot mutate the store state directly like this: store.setState("count", (count) => count + 1). The provider's state will always take precedence. This is why we do not expose the store directly, to prevent such mistakes.