npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@mindspace-io/react-akita

v1.2.9

Published

React hooks + utilities for Akita State Management

Downloads

18

Readme

React State Management

react-akita splash

Just install @mindspace-io/react-akita to use.

Purpose

A small, super powerful statemanagement library for React... using an Akita engine and Zustand-like API.

  1. Publishes a React-intuitive hook
  2. Uses ImmerJS to enforce immutability at the view layers.
  3. Encourages super-clean View components
  4. Encourages user interactions to be delegated to the business layers.
  5. Powered by the amazing Akita State Management library

This React library now provides super-powered Store createStore() function to simultaneously

  • Create a store with managed state, and
  • Use the published React hook implicitly connected to its associated store state.
  • useStore(<selector>) to easily re-render the view when the state changes.

Developers familiar with Vue will recognize this state management approach using stores and mutators:

store-view

Create a Store

The beauty of the createStore() is that a factory function is used to build the initial state.

And the factory function is actually provided the [set, get, ...] store api:

import create from '@mindspace-io/react-akita';

// Define store structure
interface StoreState {
  bears: number;
  increasePopulation: () => void;
  removeAllBears: () => void;
}

const onBuildState = ({ set, get }) => {
  return {
    // Properties
    bears: 0,

    // Mutators
    increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
    removeAllBears: () => set({ bears: 0 }),

    // Computed Properties (none here)
    // Watch Properties (none here)
  };
};

// Build a React hook connected 'live' to the store state
const useStore = createStore<StoreState>(onBuildState);

In fact, the hook is both a BOTH a React Hook and a Store API.

Using the React Hook

Now bind your components to use the state returned by the hook... and that's it!

Use the hook anywhere, no providers needed. Select your state and the component will re-render on state changes.

function BearCounter() {
  const bears = useStore((state) => state.bears);
  return <h1>{bears} around here ...</h1>;
}

function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation);
  return <button onClick={increasePopulation}>one up</button>;
}

You can also use multiple useStore() hooks - each from different stores.

import { useEmailStore, EmailState } from './email.store';
import { useEmployeeStore, EmployeeState } from './employee.store';

function AuditReport() {
  const emails = useEmailStore((state: EmailState) => state.emails);
  const people = useEmployeeStore((state: EmployeeState) => state.executives);

  return <p>
    {people.length} Executives found! <br>
    {emails.length} Emails missing.
  </p>;
}

Caution!

caution

You cannot use the same hook multiple times in the same component:

function BearCounter() {
  const bears = useBearStore((state) => state.bears);
  const increasePopulation = useBearStore((state) => state.increasePopulation);

  return <h1>{bears} around here ...</h1>;
}

This ^ will generate runtime errors since the same useStore reference can only be used once in a view.

Solution

success

The solution is to combine the two (2) selectors into a single, composite selector:

function BearCounter() {
  const selector = [(state) => state.bears, (state) => state.increasePopulation];
  const [bears, increasePopulation] = useBearStore(selector);

  return <h1 onClick={increasePopulation}>{bears} around here ...</h1>;
}

Whenever those two (2) values change, then the view will be re-rendered with the latest values.


The important concept here is that the selector is used to build a live connection between those properties in the Store state and the View component.


Using the Store API

When a store is created, the variable reference also has the following functional API:

export interface StoreApi<T extends State> extends StatusAPI {
  set: SetState<T>;
  get: GetState<T>;

  // Used to batch state changes
  applyTransaction: ApplyTransaction<T>;

  // Used during store configuration
  addComputedProperty: AddComputedProperty<T>;
  watchProperty: WatchProperty<T>;

  // notifications do NOT trigger UI re-renders
  observe: Subscribe<T>;

  // Used to announce status
  setIsLoading: SetLoading;
  setError: SetError;

  destroy: Destroy;
}

const store: StoreAPI<StoreState> = createStore<StoreState>(onStoreReady);

Using the Store API allows developers to imperatively query/update state, subscribe for change notifications, or dispose of the store.

This can be very useful for scenarios where the API is used outside a Component; the React Hook may not be available.

Special Features

  • All state emitted (via selectors) is now immutable; locked using Immer internally. Yet your mutators do not have to worry about that... the mutators work with unlocked/draft state.

Often state management requires status tracking for loading activity and error conditions.

  • Your custom state is enhanced to include Status properties: error + isLoading
  • The Store API is enhanced to include Status API functions: setIsLoading() + setError()

In addition to standard Store API, the store is also auto enhanced with the following features:

export interface StatusAPI {
  setIsLoading: (isLoading = true) => void;
  setError: (error: unknown) => void;
}

export type Status = { isLoading: boolean; error: unknown };

Live Demos

A CodeSandbox demo has been prepared to allow developers to quickly and easily play with these features:

image


Installation

Just install with:

npm install @mindspace-io/react-akita

Under the hood, this library uses immer, @datorama/akita, and rxjs; these will be automatically installed along with @mindspace-io/react-akita.