English | 简体中文
Lightweight React state management library based on React Hooks.
🕹 CodeSandbox demos 🕹 | ||||
---|---|---|---|---|
Counter | Todos |
hooks-store
is a lightweight React state management library based on hooks. It has the following core features:
- Minimal & Familiar API: No additional learning costs, easy to get started with the knowledge of React Hooks.
- Centralization: Easy to initialize data and support hooks interaction.
- Readonly API: Supports read-only state without subscribing to updates.
- Great Compatibility: Class Component Support && Perfect TypeScript Support.
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { createStore } from '@ice/hooks-store';
// 1️⃣ Create a custom hook as usual
function useCounter() {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return {
count,
increment,
};
}
const hooks = {
useCounter,
};
// 2️⃣ Create the store
const store = createStore(hooks);
// 3️⃣ Consume 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️⃣ Wrap your components with Provider
const { Provider } = store;
function App() {
return (
<Provider>
<Count />
<Button />
</Provider>
);
}
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
@ice/hooks-store requires React 16.8.0 or later.
npm install @ice/hooks-store --save
In some scenarios, you may only want to call the method returned by the hooks to update the state instead of subscribing to the update of the hooks state. For example, the button component in the "Basic example", you do not consume the state of the hooks in the component, so you may not expect the change of the state of the hooks to trigger the re-render of the component.
At this time, you can use the getHooks
API, check following example and compare them with the above example:
const { getHooks } = store;
function Button() {
function handleIncrement() {
getHooks('useCounter').increment();
}
return (
<button type="button" onClick={handleIncrement}> + </button>
);
}
In some scenarios, you might expect a state change of Hooks A to trigger a state update of Hooks B. We call this behavior as "Hooks Interaction".
For example:
- We have a useTodos Hooks that records all tasks.
- We have a useUser Hooks, in which there is a todos field, which records the number of tasks owned by the current user.
- Whenever the todos Hooks's tasks changes, the number of tasks held by users needs to be kept in sync.
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 }];
}
import { Component } from 'react';
import store from '@/store';
import useTodos from '@/hooks/useTodos';
const { withHooks } = store;
interface MapHooksToProp {
useTodos: ReturnType<typeof useTodos>; // This field is automatically added by withHooks
}
interface CustomProp {
title: string; // User defined props
}
type Props = CustomProp & MapHooksToProp;
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)}>
Remove
</button>
</div>);
})
}
</div>
);
}
}
export default withHooks('useTodos')<MapHooksToProp, Props>(Todos);
✔ | ✔ | ✔ | 9+ ✔ | ✔ | ✔ | ✔ |
Feel free to report any questions as an issue, we'd love to have your helping hand on @ice/hooks-store.
If you're interested in @ice/hooks-store, see CONTRIBUTING.md for more information to learn how to get started.
DingTalk community | GitHub issues | Gitter |
---|---|---|
issues | gitter |