Imdux
特点
-
🚀 简单高效:完全去除了redux冗余低效的样板代码,提供一把全自动的生产力工具。 -
🍧 类型安全:面向typescript用户,100%类型安全,同时摒弃interface类型预定义,改用infer,实现了state和dispatch类型推导,极大地减少了类型定义代码。 -
✈️ 目前未来:拥抱react hooks,便于typescript的类型检查和代码复用。 -
🍸 最佳实践:Imdux的目的不仅仅是提供一个库,更希望的是提供一个解决方案,探索一种react hooks的最佳实践。
开始
首先,创建一个react项目:
npx create-react-app imdux-demo
安装imdux,imdux依赖于 immer,redux,react-redux :
npm install imdux immer redux react-redux --save
在src
目录下创建文件store.js
,输入代码:
import { createAction, createStore } from "imdux";
const initialState = {
value: 0
};
const reducers = {
increase(draft, payload) {
draft.value += payload;
},
decrease(draft, payload) {
draft.value -= payload;
}
};
const counter = createAction({ initialState, reducers });
export const store = createStore({ counter }, { devtool: true });
export const { Dispatch } = store;
打开src/App.js
,输入代码:
import React from "react";
import { useSelector } from "react-redux";
import { Dispatch } from "./store";
export default function App() {
const value = useSelector(store => store.counter.value);
return (
<div>
<h1>{value}</h1>
<button onClick={() => Dispatch.counter.increase(1)}>increase</button>
<button onClick={() => Dispatch.counter.decrease(1)}>decrease</button>
</div>
);
}
打开src/index.js
,注入redux的store:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "./App";
import { store } from "./store";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store.redux}>
<App />
</Provider>,
rootElement
);
enjoy it~ 很简单,对不对?
打开redux的devtool,通过点击increase
和decrease
button,我们可以看到状态变更的历史记录:
通过观察可以发现,counter.increase
中的counter
等于 createStore({ counter })
中的counter
,而counter.increase
中的increase
等于reducers
中的increase
,也就是说,imdux会自动帮你创建redux中的action.type,你再也不需要定义字符串、写switch...case、那一套东西了。
对于typescript用户,你需要在store.ts
中带上类型:
import { createAction, createStore } from "imdux";
type State = typeof initialState; // 获得类型
type Reducers = typeof reducers; // 获得类型
const initialState = {
value: 0
};
const reducers = {
increase(draft: State, payload: number) { // draft的类型为State
draft.value += payload;
},
decrease(draft: State, payload: number) { // draft的类型为State
draft.value -= payload;
}
};
const counter = createAction<State, Reducers>({ initialState, reducers }); // 注入类型
export const store = createStore({ counter }, { devtool: true });
export const { Dispatch } = store;
这样你就可以很轻松地获得typescript的类型检查和代码提示:
你可以在浏览器中打开这个例子: javascript typescript
Imdux API
createAction
imdux中的action由两部组成:initialState
和reducers
。
通常react项目可以切割为很多小的页面或者模块。当一个页面或者模块的state需要全局管理时,你就可以为这个页面或者模块创建一个Action
,并为这个Action
起一个名字。例如,你有一个名称为home
的Action
,home.usename
需要全局管理:
const initialState = { usernmae: "" }
const reducers = {
setUsername(draft, payload) {
draft.usernmae = payload;
},
};
const home = createAction({ initialState, reducers });
一个Action
就创建好了。
对于typescript用户,你需要增加类型信息并注入:
type State = typeof initialState; // 获得类型
type Reducers = typeof reducers; // 获得类型
const home = createAction<State, Reducers>({ initialState, reducers }); // 注入类型
同时,给每一个reducer函数带上类型信息,以便在reducer内获得类型提示,这也是Dispatch函数参数类型检查的关键所在:
const reducers = {
setUsername(draft:State, payload:string) {
draft.usernmae = payload;
},
};
createStore
创建好名称为home
的Action
后,你需要使用createStore
把这个action初始化,同时将Dispatch
和Query
导出:
export const store = createStore({ home }, { devtool: true });
export const { Dispatch, Query } = store;
接下来,你就可以使用Dispatch
触发一个状态变化,更新页面:
Dispatch.home.setUsername("jack");
你可以使用Query
,同步地
获取当前状态:
console.log(Query.home.usernmae) // jack
异步请求
// TODO
最佳实践
// TODO
License
MIT