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

@nuage/react-consumer

v0.1.4

Published

旨在阐述清楚 声明式 的状态管理思路,以 React 作为例子,思路适用于所有 声明式 UI 的状态管理方案

Readme

此库是内部分享状态管理的一个产物

旨在阐述清楚 声明式 的状态管理思路,以 React 作为例子,思路适用于所有 声明式 UI 的状态管理方案

使用 create-react-app 创建一个新的工程,我们会使用 react 原生的 api 轻松实现一个状态管理:

状态管理的配置

1. 安装依赖

yarn add @nuage/react-consumer

源码可以直接看此仓库的 createStateManager.tsx 文件,代码仅有几十行。

2. 实例化 store, Provider, Consumer

import { createStateManager } from '@nuage/react-consumer/createStateManager';

// 一个多层级的对象示例,以验证immutable
const initState = {
  user: {
    info: {
      num: 0,
    },
  },
};

const { store, Provider, Consumer } = createStateManager(initState);

export { store, Provider, Consumer };

3. 在项目顶部注册 Provider

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom';
import Page from './Page';
import { Provider, Consumer } from './store';

function App() {
  return (
    <Provider>
      <Page />
    </Provider>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));

状态管理的使用

1. 编写 dispatch

整个项目的状态管理代码,只有 dispatch, 我们只需要要编写 dispatch 即可。

action,reducer 都不需要编写,immutable 也不需要现示的编写,这一切都是自动的

整个项目的状态都编写在一个个 dispatch 中

import { store } from './store';

export function dispatchOfAddNum() {
  // 在任何异步结束之后,处理状态更新
  store.setState(state => {
    // 此处执行区域是 immer 的更新函数,所以直接赋值即可,不需要返回整个 state
    state.user.info.num += 1;
  });
}

2. 在代码中使用状态和触发状态

import React from 'react';
import * as dispatchs from './dispatchs';
import { Consumer } from './store';

function Page() {
  return (
    <div className="app">
      <p>最简单的例子</p>
      <Consumer>{state => <h2>{state.user.info.num}</h2>}</Consumer>
      <button onClick={dispatchs.dispatchOfAddNum}>点击仅重绘number</button>
    </div>
  );
}

export default Page;

路由

路由最好使用 react-router, 使用 dispatch 为 history 封装一层,这样就可以很好的管理状态和路由。

createStateManagerAndRoute 对象内部实现了一个迷你的路由,可以无缝将路由也接入状态管理,旨在给出一个路由关联的思路, 具体可以查看 example/lib/createStateManagerAndRoute.tsx 文件。

我们用刚刚的例子,修改实例化 store 的文件:

import { createStateManagerAndRoute, IRouteState } from '@nuage/react-consumer/createStateManagerAndRoute';

// [注意] 需要添加route对象,我们约定使用 route 对象,用来记录路由状态
interface State extends IRouteState {}

// 一个多层级的对象示例,以验证immutable
const initState: State = {};

const { Provider, Consumer, store, Route, dispatchRoutePush, dispatchRouteBack } = createStateManagerAndRoute<State>(
  initState,
  '/app',
);

// 创建一个路由组件,捆绑 Consumer 和 path,params 的状态获取方法
const Route = createRoute(Consumer, (v: State) => v.route.path, (v: State) => v.route.params);

// 将 Route 导出,在页面中使用
export { Provider, Consumer, store, Route, dispatchRoutePush, dispatchRouteBack };

在任何一个页面使用路由, 只有当路径匹配时, 子组件才会渲染, 路由可以嵌套使用:

import { Route } from './store';

export default () => {
  return (
    <Route path="/user">
      <UserPage />
      <Route path="/user/login">
        <Login />
      </Route>
    </Route>
  );
};

切换路由, 也仅仅是两个预设好的 dispatch:

import { dispatchRoutePush, dispatchRouteBack } from './store';

// 推入一个路由
dispatchRoutePush('/some-page', { name: 'dog' });

// 返回上一次的路由
dispatchRouteBack();

单元测试

单元测试我们只需要覆盖 dispatch 的测试即可, dispatch 仅是一个个函数,测试起来非常简单:

import { dispatchOfAddNum } from '../src/dispatchs';
import store from '../src/store';

test('add card', async () => {
  await dispatchOfAddNum(10);

  // 当函dispatch执行完成,我们检查一下store是否和我们预期的值一致即可
  expect(store.state.user.info.num).toBe(10);
});

我们可以在项目中运行 yarn test 验证以上测试