@nuage/context

简易: 简化了 redux 的使用方式, 仅有 action 及 state 的概念, 且遵循 redux 单向数据流, 数据驱动页面的设计思维; - 轻量: 仅用 react 自带的 hook 及 context 实现, 源码仅有 20 行, 数据变更使用 immer 库; - 高性能: 为了更颗粒的控制组件更新, 使用 immer 进行数据的设定, 虽然是不可变数据, 但是使用过程中是无感知的;

Usage no npm install needed!

<script type="module">
  import nuageContext from 'https://cdn.skypack.dev/@nuage/context';
</script>

README

基于 hooks, context, immer 的 Redux 实现

Feature

  • 简易: 简化了 redux 的使用方式, 仅有 action 及 state 的概念, 且遵循 redux 单向数据流, 数据驱动页面的设计思维;
  • 轻量: 仅用 react 自带的 hook 及 context 实现, 源码仅有 20 行, 数据变更使用 immer 库;
  • 高性能: 为了更颗粒的控制组件更新, 使用 immer 进行数据的设定, 虽然是不可变数据, 但是使用过程中是无感知的;

安装

$ yarn add @nuage/react-context-immer

编译

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

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

// 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 createContextRedux from '@nuage/react-context';

const { store, Provider } = createContextRedux();

function actionOfChangeAge() {
  // 发起一个 dispatch, 修改全局 state, 从而更新 注册了 context 的组件
  store.dispatch(state => {
    // state 是一个 immutable 对象, 请直接修改 state 的值, 而不是重构 state
    state.age += 1;
  });
}

function Sub() {
  const { state } = React.useContext(store);

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

function App() {
  return (
    <Provider defaultState={{ age: 0 }}>
      <Sub />
      <button type="button" onClick={actionOfChangeAge}>
        change age
      </button>
    </Provider>
  );
}

异步更新

异步更新不需要引入任何新 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' }}>
      <div>app</div>
      <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 { state } = React.useContext(store);
  const { age } = state;

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

感谢阅读