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-context

v0.2.8

Published

> **注意**, 请使用 [@nuage/react-consumer](https://github.com/ymzuiku/react-consumer) 代替此库

Readme

注意, 请使用 @nuage/react-consumer 代替此库

注意, 请使用 @nuage/react-consumer 代替此库

基于 hooks, context, immer 的 Redux 实现

Feature

  • 简易: 简化了 redux 的使用方式, 仅有 action 及 state 的概念, 且遵循 redux 单向数据流, 数据驱动页面的设计思维;
  • 轻量: 仅用 react 自带的 hook 及 context 实现, 源码加注释仅有 40 行, 数据变更使用 immer 库;
  • 高性能: 为了更颗粒的控制组件更新, 使用 immer 进行数据的设定, 虽然是不可变数据, 但是使用过程中是无感知的;
  • 局部更新: 引入一个局部更新和局部更新拦截的思路,让状态管理的控制更细微

安装

$ yarn add @nuage/react-context

编译

@nuage/* 系列的库都都不会进行编译发布: 为了在不使用 Typescript 的前提下更好地利用 Javascript 的提示

此库未编译, 也不愿意编译后发布, 使用请配置 webpack 的 babel:

// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript, and some ESnext features.
{
  test: /\.(js|mjs|jsx|ts|tsx)$/,
  // 此处添加 @nuage 的正则, 使得 @nuage/* 的库会被 babel 编译
  include: [/@nuage/, paths.appSrc],
  loader: require.resolve('babel-loader'),
  ...
}

基础使用

import React from 'react';
import { render } from 'react-dom';
import createReactContext from '@nuage/react-context';

const { Provider, store } = createReactContext();

// 模拟一个异步
function fetchData() {
  return new Promise(res => {
    setTimeout(() => {
      res();
    }, 500);
  });
}

// 一个基础的 action, 用来修改状态
// 在实际项目中, action 应该统一放置一处, 不应该分散在各组件中
async function actionOfAddNum() {
  await fetchData();

  store.dispatch(state => {
    state.age += 1;
  });
}

// 点击之后, 利用 action 修改全局状态
function Changer() {
  return (
    <button type="button" onClick={actionOfAddNum}>
      add
    </button>
  );
}

// 利用 useContext 监听全局状态, 并随时进行更新
function Shower() {
  const { age } = React.useContext(store);

  return <div>age: {age}</div>;
}

function App() {
  return (
    <Provider defaultState={{ age: 0 }}>
      <Shower />
      <Changer />
    </Provider>
  );
}

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

局部更新

Flutter 问世之后,有许多状态管理方案,其中就包含 Redux 风格的方案。Flutter 的 Provider 及 flutter_redux 两个状态管理库中,都使用了一个局部更新的方式来控制重绘区域,此库根据其思路也实现了一个局部的 Consumer 组件供君使用。

Consumer 和 context.Consumer 作用相同,唯一的区别仅仅是 Consumer 可以配合 useMemo 进行更新拦截

import React from 'react';
import { render } from 'react-dom';
import createReactContext from './react-context';

const { Provider, Consumer, store } = createReactContext({ num: 0 });

function App() {
  console.log('整个组件只会渲染一次');

  return (
    <div>
      <header>
        <p>
          Only change <code>Consumer Component</code>:
        </p>
        <Consumer>
          {({ num }) => {
            console.log('此组件会被重复渲染');
            return <p>{num}</p>;
          }}
        </Consumer>

        <button
          onClick={() => {
            store.dispatch(state => {
              state.num += 1;
            });
          }}
        >
          addNumber
        </button>
      </header>
    </div>
  );
}
render(
  <Provider>
    <App />
  </Provider>,
  document.getElementById('root'),
);

局部更新的拦截

如果传递了 memo 函数, 则子组件会被 useMemo 包裹,memo 的返回值是 useMemo 的第二个参数, useMemo 的用法可阅读 React.hooks.useMemo

下面的例子,子组件只有当 state.num 改变了才会重绘,其他属性的修改会被拦截

<Consumer memo={state => [state.num]}>
  {({ num }) => {
    return <p>{num}</p>;
  }}
</Consumer>

异步更新

异步更新不需要引入任何新 API\中间键, 只需要在 action 中执行任何异步行为, 在异步结束之后进行更新

// action.js
import { store } from './createContext.js';

async function actionOfFetchUser() {
  const info = await fetch(...);

  // 在请求之后更新数据
  store.dispatch(state => {
      state.age += 1;
  });
}

工程化

我们需要将 action 分离到公共区域, 组件只需要发起 action, 获得新的数据即可

1. 创建 store 及 Provider

// createContext.js
import createContextRedux from '@nuage/react-context';

const { store, Provider } = createContextRedux();

export { store, Provide };

2. 在项目顶部声明 Provide

// App.js
import { Provide } from './createContext.js';
import Changer from './Changer';
import Shower from './Shower';

function App() {
  return (
    <Provider defaultState={{ name: 'dog' }}>
      <Changer />
      <Shower />
    </Provider>
  );
}

3. 声明修改 state 的 action

// action.js
import { store } from './createContext.js';

export function actionOfChangeAge() {
  store.dispatch(state => {
    state.age = 500;
  });
}

4. 实现两个组件, 跨组件更新

// Changer.js
import { actionOfChangeAge } from './action.js';

function Changer() {
  return <button onClick={actionOfChangeAge}>click this change age</button>;
}
// Shower.js
import { store } from './createContext.js';

function Shower() {
  // 注册 store
  const { age } = React.useContext(store);

  // 使用 userCallback 管理控制, 只有 age 修改时, 才会进行重绘
  return React.useCallback(<div>age: {age}</div>, [age]);
}

感谢阅读