Redux類適用所有React生態專案
import {
applyMiddleware,
combineReducers,
legacy_createStore as createStore,
Store,
compose,
} from "redux";
import thunk from "redux-thunk";
import {connect, Provider} from "react-redux";
import {Action as ReduxAction, AnyAction} from "redux";
type StoreState = {
[key: string]: string | number | boolean | undefined | null | unknown | void
}
type StoreMap<T = any, S = any> = {
namespace: string;
state: S | StoreState;
reducers?: {
[key: string]: (state: StoreState, params: T) => StoreState
},
[key: string]: any;
}
interface StoreStore<T = any> {
namespace: string;
state: T | StoreState;
[key: string]: any;
}
type StoreStores<T = any> = {
[key: string]: StoreStore<T>;
};
type StoreReducers<T = any> = {
[key: string]: T
}
interface Dispatch<A extends ReduxAction = AnyAction> {
<T extends A> (action: T): T
}
type Params = { [key: string]: any }
export default class Redux<T = Params> {
public static _collection: Params = {};
public dispatch: Dispatch;
public namespace: string;
public state: T = {} as T;
constructor () {
}
// 所有狀態的集合
public get collection () {
return Redux._collection;
};
// 初始化的狀態
public get store () {
return {
namespace: this.namespace,
state: this.state,
} as {
namespace: string;
state: T
};
}
// dispatch
public get action () {
return (dispatch: Dispatch) => this._renderRedux(dispatch);
}
// 狀態改變
public setState = (state: T, cb?: (newState: T) => void): T => {
this.dispatch({
type: `${this.namespace}/setState`,
state
});
const newState = {
...this.state,
...state
};
this.state = newState;
if (cb) {
cb(newState);
}
Redux._collection[this.namespace] = newState;
return newState;
};
// 建立多個狀態
public createStores (
stores: StoreStores
): Store {
return createStore(
combineReducers(
this._createReducers(
{
...stores
}
)
), compose(applyMiddleware(thunk)
)
);
}
// 根據每個store建立xxx/setState
private _createState (map: StoreMap) {
const newMap = {...map};
newMap.reducers = newMap.reducers ? newMap.reducers : {};
const newReducers: StoreReducers = {};
newReducers[`${newMap["namespace"]}/setState`] = (_state: StoreState, {state}: { state: StoreState }) => ({..._state, ...state});
newMap.reducers = newReducers;
return (state = newMap.state, action: { type: string }) => {
if (newMap.reducers && newMap.reducers[action.type]) {
return newMap.reducers[action.type](state, action);
} else {
return state;
}
};
};
private _createReducers (reducers: StoreStores): StoreReducers {
return Object.entries(reducers).reduce((preItems, item) => {
const namespace = item[1].namespace;
Redux._collection[namespace] = item[1].state;
return {
...preItems,
[namespace]: this._createState(item[1])
};
}, {});
};
private _renderRedux = (dispatch: Dispatch) => {
this.dispatch = dispatch;
return this;
};
}
export {
Dispatch,
StoreMap,
StoreReducers,
StoreState,
StoreStores,
StoreStore,
Redux,
connect,
Provider,
};
繼承Redux
import Redux from "@/common/redux/redux";
interface State {
desc?: string;
title?: string;
}
// 繼承Redux
class CommonAction extends Redux<State> {
constructor () {
super();
// 這個狀態的名字(必須要有)
this.namespace = 'common';
// 需要管理的單個狀態(必須要有)
this.state = {
a: '',
b: '',
}
}
public onChange = async () => {
// 所有狀態的資料 this.collection['common'] = this.state
this.collection;
// 當前common狀態
this.state;
// 修改common狀態
this.setState({ a: 1, b: 2 });
// 修改其他狀態(這裡是home狀態)
this.dispatch({type: 'home/setState', {c: 3, d: 4}})
};
}
const common = new CommonAction();
export const commonAction = common.action;
export const commonStore = common.store;
把資料放到全域性(可以放多個Store)
import React from "react";
import Taro from "@tarojs/taro";
import Redux, {Provider} from "@/common/redux/redux";
// 各個狀態
import {commonStore} from "@/common/redux/common";
import {homeStore} from "@/common/redux/home";
const createStoreChildren = (children) => {
// 狀態各個註冊
const stores = React.useRef(new Redux().createStores({
commonStore,
homeStore
})).current;
return <Provider store={stores}>
{children}
</Provider>;
};
// createStoreChildren用來包裹最外層
export default createStoreChildren;
單個頁面或者元件引入使用
...
export default connect((e: {}) => {
// 把當前頁面或者元件匯入用到的狀態值
return {
a: e['common'].a,
b: e['common'].b,
c: e['home'].c,
d: e['home'].d,
};
}, (dispatch) => {
// 把當前頁面或者元件匯入用到的方法
const home = homeAction(dispatch);
const common = commonAction(dispatch);
return {
dispatch,
setHomeState: home.setState,
homeInit: home.homeInit,
setCommonState: common.setState,
onChange: common.onChange,
};
})(Index);