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

react-consumer

v1.6.2

Published

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

Readme

满足声明式、单一状态源的前提下,控制重绘的颗粒度

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

只监听不可变对象有差异时,对颗粒 React 节点进行更新的状态管理方案,使用 redux 一样的思路,它是声明式的、单一数据源的

整个状态管理方案的思路请查阅 Keynote: React 状态管理之温故知新.key

这个 Keynote 是内部演讲的产物,每一页均有注释,请激活 Keynote 的演讲注释搞即可查看。

状态管理的配置

1. 安装依赖

yarn add react-consumer

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

2. 实例化 store, Consumer

import ReactConsumer from 'react-consumer';
import produce from 'immer';

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

// 编写更新处理方法,这里推荐使用 immer 来使用不可变对象
const updater = (state, event) => {
  return produce(state, draft => {
    event(draft);
  });
};

const { store, Consumer } = ReactConsumer.createStateManager(initState, updater);

export { store, Consumer };

状态管理的使用

1. 编写 action

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

import { store } from './store';

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

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

Consumer API

| props | 类型 | 描述 | | --------- | -------------------------------------- | --------------------------------------------------------------------------------- | | subscribe | (state) => any[] | 返回一个数组对象, 只有当数组对象变更了, 才会更新组件 | | memo | any[] | 组件内部拦截了更新派发,若有非 subscribe 之外的上下文依赖更新,需要声明在 memo 中 | | onMount | (...subscribeDatas) => void | 当组件 onMount 时的回调 | | onUnmount | (...subscribeDatas) => void | 当组件将要销毁之前的回调 | | onUpdate | (...subscribeDatas) => void | 当组件将要更新之前的回调 | | children | (...subscribeDatas) => React.Element | Consumer 的子组件是一个函数(renderProps), 函数参数是 memo 对象和 state |

示例:

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

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

export default Page;

扩展阅读

我们都知道 redux 给我们带来一个可能就是时间旅行时间旅行之所以可行是因为整个项目都被一个单一数据管理,我们只需要修改状态数据,整个应用就可以随时切换到相应的状态。

我们或许不需要时间旅行,但是我们需要让整个应用满足单一数据源,由一个状态管理。

我们如果要确保整个项目 UI 都由一个状态管理,相当于整个项目 UI 都抽象成无副作用的函数,那么还需要讲路由也纳入状态管理中。

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

react-consumer 内置了一个路由扩展模块,它帮我们无缝实现了以上功能,它非常接近 react-route,但是有些许不一样。具体可以查看:

使用 react-consumer 的路由扩展模块

单元测试

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

import { actionOfAddNum } from '../src/actions';
import { store } from '../src/store';

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

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

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