mirror of https://github.com/usememos/memos
chore: remove customize redux
parent
8e01eb8702
commit
0b3c77c79c
@ -1,31 +0,0 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
import { Store } from "./createStore";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
children: React.ReactElement;
|
|
||||||
store: Store<any, any>;
|
|
||||||
context: React.Context<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toy-Redux Provider
|
|
||||||
* Just for debug with the app store
|
|
||||||
*/
|
|
||||||
const Provider: React.FC<Props> = (props: Props) => {
|
|
||||||
const { children, store, context: Context } = props;
|
|
||||||
const [appState, setAppState] = useState(store.getState());
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const unsubscribe = store.subscribe((ns) => {
|
|
||||||
setAppState(ns);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribe();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return <Context.Provider value={appState}>{children}</Context.Provider>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Provider;
|
|
@ -1,36 +0,0 @@
|
|||||||
import { Action, Reducer, State } from "./createStore";
|
|
||||||
|
|
||||||
interface ReducersMapObject<S extends State = any, A extends Action = any> {
|
|
||||||
[key: string]: Reducer<S, A>;
|
|
||||||
}
|
|
||||||
|
|
||||||
type StateFromReducersMapObject<M> = M extends ReducersMapObject
|
|
||||||
? { [P in keyof M]: M[P] extends Reducer<infer S, any> ? S : never }
|
|
||||||
: never;
|
|
||||||
|
|
||||||
function combineReducers<S extends State, A extends Action>(reducers: ReducersMapObject): Reducer<S, A> {
|
|
||||||
const reducerKeys = Object.keys(reducers);
|
|
||||||
const finalReducersObj: ReducersMapObject = {};
|
|
||||||
|
|
||||||
for (const key of reducerKeys) {
|
|
||||||
if (typeof reducers[key] === "function") {
|
|
||||||
finalReducersObj[key] = reducers[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((state: StateFromReducersMapObject<typeof reducers> = {}, action: A) => {
|
|
||||||
let hasChanged = false;
|
|
||||||
const nextState: StateFromReducersMapObject<typeof reducers> = {};
|
|
||||||
|
|
||||||
for (const key of reducerKeys) {
|
|
||||||
const prevStateForKey = state[key];
|
|
||||||
const nextStateForKey = finalReducersObj[key](prevStateForKey, action);
|
|
||||||
nextState[key] = nextStateForKey;
|
|
||||||
hasChanged = hasChanged || nextStateForKey !== prevStateForKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasChanged ? nextState : state;
|
|
||||||
}) as any as Reducer<S, A>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default combineReducers;
|
|
@ -1,63 +0,0 @@
|
|||||||
export type State = Readonly<Record<string, any>>;
|
|
||||||
export type Action = {
|
|
||||||
type: string;
|
|
||||||
payload: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Reducer<S extends State, A extends Action> = (s: S, a: A) => S;
|
|
||||||
type Listener<S extends State> = (ns: S, ps?: S) => void;
|
|
||||||
type Unsubscribe = () => void;
|
|
||||||
|
|
||||||
export interface Store<S extends State, A extends Action> {
|
|
||||||
dispatch: (a: A) => void;
|
|
||||||
getState: () => S;
|
|
||||||
subscribe: (listener: Listener<S>) => Unsubscribe;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toy-Redux
|
|
||||||
* @param preloadedState initial state
|
|
||||||
* @param reducer reducer pure function
|
|
||||||
* @returns store
|
|
||||||
*/
|
|
||||||
function createStore<S extends State, A extends Action>(preloadedState: S, reducer: Reducer<S, A>): Store<Readonly<S>, A> {
|
|
||||||
const listeners: Listener<S>[] = [];
|
|
||||||
let currentState = preloadedState;
|
|
||||||
|
|
||||||
const dispatch = (action: A) => {
|
|
||||||
const nextState = reducer(currentState, action);
|
|
||||||
const prevState = currentState;
|
|
||||||
currentState = nextState;
|
|
||||||
|
|
||||||
for (const cb of listeners) {
|
|
||||||
cb(currentState, prevState);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const subscribe = (listener: Listener<S>) => {
|
|
||||||
let isSubscribed = true;
|
|
||||||
listeners.push(listener);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (!isSubscribed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = listeners.indexOf(listener);
|
|
||||||
listeners.splice(index, 1);
|
|
||||||
isSubscribed = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getState = () => {
|
|
||||||
return currentState;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
dispatch,
|
|
||||||
getState,
|
|
||||||
subscribe,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default createStore;
|
|
@ -1,29 +0,0 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
type State = Readonly<Record<string, any>>;
|
|
||||||
interface Action {
|
|
||||||
type: string;
|
|
||||||
}
|
|
||||||
type Listener<S extends State> = (ns: S, ps?: S) => void;
|
|
||||||
|
|
||||||
interface Store<S extends State, A extends Action> {
|
|
||||||
dispatch: (a: A) => void;
|
|
||||||
getState: () => S;
|
|
||||||
subscribe: (listener: Listener<S>) => () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function useSelector<S extends State, A extends Action>(store: Store<S, A>): S {
|
|
||||||
const [state, setState] = useState(store.getState());
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const unsubscribe = store.subscribe((ns) => {
|
|
||||||
setState(ns);
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribe();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
Loading…
Reference in New Issue