Skip to content
This repository has been archived by the owner on Feb 8, 2023. It is now read-only.

Latest commit

 

History

History
243 lines (187 loc) · 7.71 KB

README.zh-CN.md

File metadata and controls

243 lines (187 loc) · 7.71 KB

English | 简体中文

hooks-store

基于 React Hooks 的轻量级状态管理框架。

NPM version Package Quality build status NPM downloads Known Vulnerabilities David deps

🕹 CodeSandbox demos 🕹
Counter Todos

简介

hooks-store 是基于 React Hooks 实现的轻量级状态管理框架,具有以下特征:

  • 最小和熟悉的 API: 没有额外的学习成本,只需要了解 React Hooks;
  • 中心化: 很方便地进行数据初始化和状态联动;
  • 状态只读 API: 支持只读状态而不订阅状态的更新;
  • 良好的兼容性: 类组件兼容和良好的 TypeScript 类型检查和推断。

快速开始

import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { createStore } from '@ice/hooks-store';

// 1️⃣ 自定义 Hooks
function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);

  return {
    count,
    increment,
  };
}

const hooks = {
  useCounter
};

// 2️⃣ 创建 Store
const store = createStore(hooks);

// 3️⃣ 消费 Hooks
const { useHooks } = store;
function Button() {
  const { increment } = useHooks('useCounter');
  return (
    <button type="button" onClick={increment}> + </button>
  );
}
function Count() {
  const { count } = useHooks('useCounter');
  return (<span>{count}</span>);
}

// 4️⃣ 通过 Provider 绑定 Store 到视图
const { Provider } = store;
function App() {
  return (
    <Provider>
      <Count />
      <Button />
    </Provider>
  );
}

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

安装

使用 @ice/hooks-store 需要 React 在 16.8.0 版本以上。

npm install @ice/hooks-store --save

进阶用法

只读不订阅更新

在某些场景下,您可能只希望调用 Hooks 返回的方法更新状态而不订阅 Hooks 状态的更新。 例如「快速开始」示例中的 Button 组件,您没有在组件中消费 Hooks 的状态,因此可能不期望 Hooks 状态的变化触发组件的重新渲染。 这时候您可以使用 getHooks API,看下面的示例,可以与上面的示例进行比较:

const { getHooks } = store;
function Button() {
  function handleIncrement() {
    getHooks('useCounter').increment();
  }
  return (
    <button type="button" onClick={handleIncrement}> + </button>
  );
}

Hooks 联动

在某些场景下,您可能期望 A Hooks 的某个状态的变更触发 B Hooks 某个状态的更新。我们把这种行为称为「Hooks 联动」。 例如下面的场景:

  • 我们有一个 useTodos,记录了所有的任务列表。
  • 我们有一个 useUser,该 hooks 返回一个 todos 字段,记录了当前用户拥有的任务数。
  • 每当 useTodos 的任务列表发生了变更,用户持有的任务数就需要保持同步。

方式一:状态订阅

import { useEffect, useState } from 'react';
import produce from 'immer';
import '@/store';

function useUser() {
  const [state, setState] = useState({ todos: 0 });
  const [todos] = store.useHooks('useTodos');

  useEffect(() => {
    setState(produce((draft) => {
      draft.todos = todos.length;
    }));
  }, [ todos ]);

  return [state, setState];
}

方式二:方法调用

import { useState } from 'react';
import produce from 'immer';
import '@/store';

function useTodos() {
  const [state, setState] = useState([
    {
      name: 'angular',
    },
  ]);

  function setTodos(todos) {
    setState(todos);

    const [, setUser] = store.getHooks('useUser');
    setUser(produce((draft) => {
      draft.todos = todos.length;
    }));
  }
 
  return [state, { setTodos }];
}

在类组件中使用

您仍然可以在类组件中获取和订阅 Hooks:

import { Component } from 'react';
import store from '@/store';
import useTodos from '@/hooks/useTodos';

const { withHooks } = store;

interface MaHooksToProp {
  useTodos: ReturnType<typeof useTodos>; // 这个字段是 withHooks 自动添加的
}

interface CustomProp {
  title: string; // 用户自定义的 props
}

type Props = CustomProp & MaHooksToProp;

class Todos extends Component<Props> {
  render() {
    const { title, useTodos } = this.props;
    const [ state, actions ] = useTodos;
    return (
      <div>
        {
          state.map(({ name }, index) => {
            return (<div key={index}>
              {name}
              <button onClick={() => actions.remove(index)}>
                删除
              </button>
            </div>);
          })
        }
      </div>
    );
  }
}

export default withHooks('useTodos')<MaHooksToProp, Props>(Todos);

浏览器兼容

Chrome Firefox Edge IE Safari Opera UC
9+ ✔

参与贡献

欢迎通过 issue 反馈问题。

如果对 @ice/hooks-store 感兴趣,请参考 CONTRIBUTING.md 学习如何贡献代码。

社区

钉钉群 GitHub issues Gitter
issues gitter

License

MIT