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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@helux/store-pinia

v5.0.5

Published

Intuitive, type safe, light and flexible Store (based on helux) for React with DevTools support

Downloads

209

Readme

helux-store-pinia

一个优雅的类似 pinia 开发体验的 react 状态管理库,基于 helux 开发

安装

npm i @helux/store-pinia

简单例子

const storeCtx = defineStore('Counter', {
  // 定义状态(必须)
  state: () => ({ count: 0 }),
  // 定义带缓存的派生属性(可选)
  getters: {
    countDouble() {
      return this.count * 2;
    },
  },
  // 定义方法修改状态(可选)
  actions: {
    // 同步方法
    addCount(payload: number) {
      this.count = payload;
    },
    // 异步方法
    async addCountAsync(paload: number) {
      await delay();
      this.count = payload;
      // or
      // this.addCount(payload);
    },
  },
});

复杂例子

创建 store

const storeCtx = defineStore('BookStore', {
  // 定义状态(必须)
  state: () => ({ list: [] as IBook[], page: 1, size: 10, total: 8, mountCount: 0 }),
  // 定义带缓存的派生属性(可选)
  getters: {
    // 由 state 派生出 totalPlus,上游依赖不变化时此函数不再重复计算
    totalPlus() {
      return this.total + 1;
    },
    // 由其他 getters 派生出 totalPlus2,上游依赖不变化时此函数不再重复计算
    totalPlus2() {
      return this.totalPlus + 100;
    },
  },
  // 定义方法修改状态(可选)
  actions: {
    // 同步方法
    changeTotal(payload: number) {
      this.total = payload;
    },
    // 异步方法
    async fetchList(payload: { page: number; size: number }, p2: number) {
      console.log(payload.page, payload.size);
      await delay();
      const { list, total } = await Promise.resolve({
        list: [
          { id: '1', name: `state_${Date.now()}`, price: 100 },
          { id: '2', name: `helex_${Date.now()}`, price: 100 },
        ],
        total: 10,
      });
      this.list = list;
      this.total = total;
    },
  },
  // 定义生命周期(可选),包含 willMount mounted willUnmount, 含义见 ILifeCycle 定义,
  // lifecycle 方法可访问 actions 里的方法,也可以访问 state 并修改,
  // 但是在 actions 里是访问不到 lifecycle 的,只能由框架负责调用,
  lifecycle: {
    mounted() {
      this.mountCount += 1;
    },
  },
});

组件里使用

function Shop() {
  const store = storeCtx.useStore();
  const ld = storeCtx.useLoading();
  // fetchList 的运行状态,如关系其他函数运行状态,可从 ld 继续解构获取到
  const { loading, err, ok } = ld.fetchList;

  return (
    <div>
      {loading && <h1>fetching books</h1>}
      {err && <h1>{err.message}</h1>}
      {ok
        && store.list.map((v) => (
          <div key={v.id}>
            name:{v.name} price:{v.price}
          </div>
        ))}
      <h3>total {store.total}</h3>
      <h3>totalPlus {store.totalPlus}</h3>
      <button onClick={() => store.fetchList({ page: 1, size: 10 }, 222)}>more</button>
      <button onClick={() => store.changeTotal(Date.now())}>change total</button>
      <button onClick={() => storeCtx.reset()}>reset</button>
    </div>
  );
}

信号感知

// 细粒度绑定
function Other() {
  return (
    <div>
      total: {$(storeCtx.state.totalPlus)}
      <br />
      totalPlus2: {$(storeCtx.state.totalPlus2)}
      <br />
      mountCount: {$(storeCtx.state.mountCount)}
    </div>
  );
}

打印快照

function Snap() {
  storeCtx.useStore();
  return (
    <div style={{ border: '3px solid red', padding: '10px', margin: '12px' }}>
      Snap: {JSON.stringify(storeCtx.getSnap())}
      <br />
      GettersSnap: {JSON.stringify(storeCtx.getGettersSnap())}
      <button
        onClick={() => {
          console.log(storeCtx);
        }}
      >
        see store context
      </button>
    </div>
  );
}

添加 redux devtool 插件

import { HeluxPluginDevtool } from '@helux/plugin-devtool';

import { addPlugin } from '@helux/store-pinia';
addPlugin(HeluxPluginDevtool);

下图即添加开发差距后的效果

Image

对应代码如下

import { defineStore } from '@helux/store-pinia';

interface IBook {
  id: string;
  name: string;
  price: number;
}

const delay = (ms = 1000) => new Promise((r) => setTimeout(r, ms));
export const storeCtx = defineStore('DefineStoreDemo', {
  state: () => ({
    list: [] as IBook[],
    page: 1,
    size: 10,
    total: 221,
    mountCount: 0,
    time: 0,
    a: 1,
    b: 2,
    c: 3,
    d: 4,
  }),
  getters: {
    // 由 state 派生出 totalPlus,上游依赖不变化时此函数不再重复计算
    totalPlus() {
      return this.total + 1;
    },
    // 由其他 getters 派生出 totalPlus2,上游依赖不变化时此函数不再重复计算
    totalPlus2() {
      return this.totalPlus + 100;
    },
  },
  actions: {
    // 同步方法
    changeTotal(payload: number) {
      this.total = payload;
    },
    async otherFn(test?: number, test2?: number) {
      await delay(); // ❌ <--- 此处之前无变更,故不会提交
      this.a = Date.now();
      await delay(); // ✅ <--- 在此之前有数据变更,触发提交
      this.b = Date.now();
      await delay(); // ✅<--- 在此之前有数据变更,触发提交
      this.c = Date.now();
      // ✅<--- 结束 action,在此之前有数据变更,触发提交
    },
    // 异步方法
    async fetchList(payload: { page: number; size: number }, p2: number) {
      console.log('START fetchList', payload.page, payload.size);
      await delay(); // ❌ <--- 此处之前无变更,故不会提交
      this.a = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      this.b = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      this.c = Date.now();
      await delay(); // <--- ✅ 在此之前有数据变更,触发提交
      await this.otherFn(111, 222);
      const { list, total } = await Promise.resolve({
        list: [
          { id: '1', name: `state_${Date.now()}`, price: 100 },
          { id: '2', name: `helex_${Date.now()}`, price: 100 },
        ],
        total: 10,
      });
      this.list = list;
      this.total = total;
      console.log('End fetchList', payload.page, payload.size);
      // ✅<--- 结束 action,在此之前有数据变更,触发提交
    },
  },
});

添加自定义插件( 接收来自 helux 内部的各种事件并做对应处理 )

import { addPlugin, IPlugin } from '@helux/store-pinia';

const MyPlugin: IPlugin = {
  install(pluginCtx) {
    pluginCtx.on('ON_SHARE_CREATED', (dataInfo) => {
      // do some staff here
      // console.log('ON_SHARE_CREATED', dataInfo);
    });
    pluginCtx.on('ON_DATA_CHANGED', (dataInfo) => {
      // console.log('ON_DATA_CHANGED', dataInfo);
    });
  },
  name: 'MyPlugin',
};

addPlugin(MyPlugin);

添加自定义中间件(中间件在变更提交之前按添加顺序依次执行)

import { addMiddleware, Middleware } from '@helux/store-pinia';

const myMiddleware: Middleware = (mid) => {
  if (mid.moduleName) {
    // 来自某个模块,修改一下时间戳
    mid.draft.timestamp = new Date();
  }
};

addMiddleware(myMiddleware);