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

minsto

v1.2.6

Published

A mini store for javascript/React app

Downloads

17

Readme

Minsto

A mini store for javascript/React app

Features

  1. Zero configuration
  2. No boilerplate
  3. Extensive TypeScript support
  4. Global, shared, or component level stores
  5. Plugins supported
  6. React Suspense supported
  7. Future action listening supported
  8. Cancellable action dispatching supported
  9. React hooks based API
  10. Computed properties (support async mode) - i.e. derived data
  11. Data fetching / side effects
  12. Local store supported
  13. React Native supported
  14. Hot Reloading supported
  15. Reactotron supported

Get Started

Installation

npm install minsto --save

Step 1 - Create your store

import minsto from "minsto";

const todoStore = minsto({
  state: {
    items: ["Create store", "Use the store"],
  },
  actions: {
    add(store, payload /* item title */) {
      // state.items is immutable
      // we must use array.concat to create new copy of items and append new item at end
      store.items = store.items.concat(payload);
    },
  },
});

Step 2 - Use the store

import React, { useRef } from "react";
import todoStore from "./todoStore";
import useStore from "minsto/react";

function TodoList() {
  const inputRef = useRef();
  const { todos, add } = useStore(todoStore, (store) => {
    return {
      todos: store.items,
      add: store.add,
    };
  });
  return (
    <div>
      <input ref={inputRef} />
      <button onClick={() => add(inputRef.current.value)}>Add</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

The useStore hook has the following signature.

const result = useStore(CounterStore, (store) => {
  return {
    count: store.count,
    increase: store.increase,
  };
});
console.log(result.count, result.increase);

The hook accepts a storeMapper function. The storeMapper function will be provided your input store and should return the slice of state or actions required by your component. Anytime an update occurs on your store the storeMapper function will be executed, and if the newly mapped result does not equal the previously mapped result your component will be rendered with the new value.

Using actions to update state

In this section we will tell you how to update store state

Defining actions on our model

We are going to define two actions on our counterStoreModel; one to increase count state, and another to decrease count state. Action is pure function that retrieves two arguments (store object and action payload)

const counterStoreModel = {
  state: {
    count: 0,
  },
  // all action definitions must be placed inside actions block
  actions: {
    increase(store, payload) {
      store.count++;
    },
    decrease(store, payload) {
      store.count--;
    },
  },
};

Because action is pure function, you can write unit test easily

test("increase", () => {
  const state = { count: 0 };
  counterStoreModel.actions.increase(state);
  expec(state.count).toBe(1);
});

Using component store

Counter App with custom store hook

Computed Properties

Computed properties are the perfect candidate to help us clean up the more advanced state mapping that is happening within some of our application's components. Let's refactor each derived data case.

First up, let's add a computed property to represent the total todo items.

const todoModel = {
  state: {
    todos: [
      { id: 1, title: "todo 1", completed: false },
      { id: 2, title: "todo 2", completed: true },
    ],
  },
  computed: {
    total: (state) => state.todos.length,
  },
};

Next up, we will add a computed property to represent the completed todos and active todos.

const todoModel = {
  state: {
    todos: [
      { id: 1, title: "todo 1", completed: false },
      { id: 2, title: "todo 2", completed: true },
    ],
  },
  computed: {
    total: (state) => state.todos.length,
    completed: (state) => state.todos.filter((todo) => todo.completed).length,
    active: (state) => state.todos.filter((todo) => !todo.completed).length,
  },
};

Computed properties optionally allow you to provide an array of state resolver functions as the first argument to the computed property definition. These state resolver functions will receive the state that is local to the computed property, as well as the entire store state, and allow you to resolve specific slices of state that your computed function will take as an input.

const todoModel = {
  state: {
    todos: [
      { id: 1, title: "todo 1", completed: false },
      { id: 2, title: "todo 2", completed: true },
    ],
  },
  computed: {
    total: (state) => state.todos.length,
    completed: (state) => state.todos.filter((todo) => todo.completed).length,
    active: (state) => state.todos.filter((todo) => !todo.completed).length,
    // show todo list stats
    stats: [
      // named computed properties / state resolvers
      "total",
      "completed",
      "active",
      (total, completed, active) => ({ total, completed, active }),
    ],
  },
};

Local Store

If you don't want to mess many things into the global state, you can use local store to split app logics that used to only specified component. The local store instance stored in host component. It will be removed when its host component is unmounted. A host component can contain many local store, local store model can be reused by many components.

import { useLocalStore } from "minsto/react";
const CounterModel = {
  state: {
    count: 0,
    step: 1,
  },
  actions: {
    increase(store) {
      store.count += store.step;
    },
  },
};
const Counter = ({ step = 1 }) => {
  const store = useLocalStore(CounterModel);
  // pass step prop to store
  store.step = step;

  return <h1 onClick={store.increase}>{store.count}</h1>;
};

Working with Development Tools

Reactotron

Install reactotron-redux

npm install --save-dev reactotron-redux

Configuring

import Reactotron from "reactotron";
import { reactotronRedux } from "reactotron-redux";
import minsto from "minsto";
import { connectReactotronRedux } from "minsto/reactotron";
const reactotron = Reactotron.configure({ name: "React Native Demo" })
  .use(reactotronRedux())
  .connect();

const storeEnhander = reactotron.createEnhancer();
const counterStore = minsto({
  state: { count: 0 },
  actions: {
    increase: (store) => store.count++,
  },
});

connectReactotronRedux(storeEnhander, counterStore);

Examples

  1. Counter App
  2. Counter App using Local Store
  3. Todo App
  4. Movie Search using Async Computed Prop
  5. Animation using GSAP