Skip to content

Commit

Permalink
support reduxDevTool
Browse files Browse the repository at this point in the history
  • Loading branch information
MrWangJustToDo committed Nov 10, 2023
1 parent 8b7178a commit 6207706
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 36 deletions.
2 changes: 1 addition & 1 deletion app/.vitepress/theme/components/createState.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from "react";
import * as ReactDOM from "react-dom/client";
const divRef = ref<HTMLElement | null>(null);
const useCountState = createState(withNamespace(() => ({ data: { count: 1 } }), { namespace: "count" }));
const useCountState = createState(withNamespace(() => ({ data: { count: 1 } }), { namespace: "count", reduxDevTool: true }));
const App = () => {
const count = useCountState((state) => state.data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const useCountState_v2 = createState(withActions(() => ({ count: 1 }), { generat
const useCountState_v3 = createState(withActions(() => ({ count: 1 }), { generateActions: (state) => { return { add: (v) => { console.log(v); state.count++ }, del: () => state.count-- } } }));
const useCountState_v4 = createState(() => ({ count: 1 }), { withActions: (state) => { return { add: (v) => { console.log(v); state.count++ }, del: () => state.count-- } }, withNamespace: 'count_4' });
const useCountState_v4 = createState(withNamespace(() => ({ count: 1 }), { namespace: 'foo_2', reduxDevTool: true }), { withActions: (state) => { return { add: (v) => { console.log(v); state.count++ }, del: () => state.count-- } }, withNamespace: 'count_4' });
const App = () => {
const { count, add } = useCountState_v4();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import { createState, withActions, withPersist } from "reactivity-store";
import { createState, withActions, withNamespace, withPersist } from "reactivity-store";
import * as React from "react";
import * as ReactDOM from "react-dom/client";
const divRef = ref<HTMLElement | null>(null);
// const useCountState = createState(withPersist(withActions(() => ({ data: { count: 1 } }), { generateActions: (state) => ({ add: () => state.data.count++, del: () => state.data.count-- }) }), { key: 'foo' }));
const useCountState = createState(withActions(withPersist(() => ({ data: { count: 1 } }), { key: 'foo' }), { generateActions: (state) => ({ add: () => state.data.count++, del: () => state.data.count-- }) }));
const useCountState = createState(withNamespace(withActions(() => ({ data: { count: 1 } }), { generateActions: (state) => ({ add: () => state.data.count++, del: () => state.data.count-- }) }), { namespace: 'foo1', reduxDevTool: true }));
const App = () => {
const { count, add } = useCountState((state) => {
Expand Down
8 changes: 6 additions & 2 deletions packages/r-store/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ export declare type StateWithMiddleware<T, P> = {
["$$__state__$$"]: T;
["$$__middleware__$$"]: Record<string, unknown>;
["$$__actions__$$"]: P;
["$$__namespace__$$"]: string;
["$$__namespace__$$"]: {
namespace?: string;
reduxDevTool?: boolean;
};
};

/**
Expand Down Expand Up @@ -256,7 +259,7 @@ export declare type UseSelectorWithStore<T> = {
/**
* @public
*/
export declare const version = "0.2.5";
export declare const version = "0.2.6";

/**
* @public
Expand Down Expand Up @@ -291,6 +294,7 @@ export declare function withNamespace<T extends Record<string, unknown>>(setup:
*/
export declare type WithNamespaceProps = {
namespace: string;
reduxDevTool?: boolean;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/r-store/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "reactivity-store",
"version": "0.2.5",
"version": "0.2.6",
"author": "MrWangJustToDo",
"license": "MIT",
"description": "a reactive store, make you write reactive logic in react app just like zustand",
Expand Down
55 changes: 38 additions & 17 deletions packages/r-store/src/shared/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,44 @@ export const delDevController = (controller: Controller, state: any) => {
}
};

// cache state which has connect to devtool
const devToolMap: Record<string, any> = {};

/**
* @internal
*/
// export const connectDevTool = (name: string, actions: Record<string, Function>, state: any) => {
// if (window.__REDUX_DEVTOOLS_EXTENSION__ && typeof window.__REDUX_DEVTOOLS_EXTENSION__.connect === "function") {
// const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name });
// devTools.init(state);
// const action = { type: "name/anonymous" };
// return Object.keys(actions).reduce((p, c) => {
// p[c] = (...args) => {
// const re = actions[c](...args);
// devTools.send({ ...action, args }, JSON.parse(JSON.stringify(state)));
// return re;
// };
// return p;
// }, {})
// } else {
// return actions;
// }
// };
export const connectDevTool = (name: string, actions: Record<string, Function>, state: any) => {
if (window && window.__REDUX_DEVTOOLS_EXTENSION__ && typeof window.__REDUX_DEVTOOLS_EXTENSION__.connect === "function") {
if (devToolMap[name] && devToolMap[name] !== state) {
console.warn(`[reactivity-store/middleware] can not connect the devtool with same 'namespace' but with different state object!`);
return actions;
}
const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name });
// make the state in the devtool as a immutable object
devToolMap[name] = JSON.parse(JSON.stringify(state));
const obj = { ...devToolMap };
try {
Object.freeze(obj);
} catch {
void 0;
}
devTools.init(obj);
const action = { type: "name/anonymous" };
return Object.keys(actions).reduce((p, c) => {
p[c] = (...args) => {
const re = actions[c](...args);
const nextObj = { ...devToolMap, [name]: JSON.parse(JSON.stringify(state)) };
try {
Object.freeze(nextObj);
} catch {
void 0;
}
devTools.send({ ...action, $payload: args }, nextObj);
return re;
};
return p;
}, {});
} else {
return actions;
}
};
10 changes: 8 additions & 2 deletions packages/r-store/src/state/_internal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { reactive, toRaw } from "@vue/reactivity";

import { connectDevTool } from "../shared/dev";
import { isServer } from "../shared/env";
import { createHook } from "../shared/hook";
import { createLifeCycle } from "../shared/lifeCycle";
import { checkHasFunction, checkHasReactive, checkHasSameField } from "../shared/tools";
Expand Down Expand Up @@ -45,7 +47,7 @@ export function internalCreateState<T extends Record<string, unknown>, P extends
// handle withActions middleware;
const initialState = getFinalState(state) as T;

const actions = getFinalActions(state);
let actions = getFinalActions(state);

const namespace = getFinalNamespace(state);

Expand All @@ -70,11 +72,15 @@ export function internalCreateState<T extends Record<string, unknown>, P extends
sameField.forEach((key) => console.warn(`[reactivity-store] duplicate key: [${key}] in 'state' and 'actions' from createState, this is a unexpected usage`));
}

if (__DEV__ && namespace.reduxDevTool && !isServer) {
actions = connectDevTool(namespace.namespace, actions, rawState) as P;
}

const reactiveState = reactive(initialState);

const deepSelector = option?.withDeepSelector ?? true;

const useSelector = createHook<T, P & L>(reactiveState, rawState, lifeCycle, deepSelector, namespace, actions as P & L);
const useSelector = createHook<T, P & L>(reactiveState, rawState, lifeCycle, deepSelector, namespace.namespace, actions as P & L);

return useSelector;
}
7 changes: 3 additions & 4 deletions packages/r-store/src/state/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ export function withNamespace<T extends Record<string, unknown>, P extends Recor

const actions = getFinalActions(_initialState);

const namespace = getFinalNamespace(_initialState);

if (__DEV__ && (options.namespace === "$$__ignore__$$" || options.namespace === "$$__persist__$$")) {
console.warn(`[reactivity-store/namespace] current namespace: '${options.namespace}' is a internal namespace, try to use another one`);
}
Expand All @@ -244,16 +246,13 @@ export function withNamespace<T extends Record<string, unknown>, P extends Recor
}
setNamespaceMap(options.namespace, initialState);

// if (!alreadyHasNameSpace && !isServer && options.reduxDevTool && initialState) {
// actions = connectDevTool(options.namespace, actions, initialState) as P;
// }
}

return {
["$$__state__$$"]: initialState,
["$$__actions__$$"]: actions,
["$$__middleware__$$"]: middleware,
["$$__namespace__$$"]: options.namespace,
["$$__namespace__$$"]: { ...namespace, ...options },
};
},
{ name: "withNamespace" }
Expand Down
8 changes: 4 additions & 4 deletions packages/r-store/src/state/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type StateWithMiddleware<T, P> = {
["$$__state__$$"]: T;
["$$__middleware__$$"]: Record<string, unknown>;
["$$__actions__$$"]: P;
["$$__namespace__$$"]: string;
["$$__namespace__$$"]: { namespace?: string; reduxDevTool?: boolean };
};

/**
Expand Down Expand Up @@ -59,7 +59,7 @@ export type WithActionsProps<T, P> = {
*/
export type WithNamespaceProps = {
namespace: string;
// reduxDevTool?: boolean;
reduxDevTool?: boolean;
};

/**
Expand Down Expand Up @@ -114,7 +114,7 @@ export const getFinalActions = <T extends Record<string, unknown>, P extends Rec
* @internal
*/
export const getFinalNamespace = <T extends Record<string, unknown>, P extends Record<string, Function>>(state: MaybeStateWithMiddleware<T, P>) => {
if (state["$$__state__$$"]) return (state["$$__namespace__$$"] || "") as string;
if (state["$$__state__$$"]) return (state["$$__namespace__$$"] || {}) as { namespace?: string; reduxDevTool?: boolean };

return "";
return {} as { namespace?: string; reduxDevTool?: boolean };
};
7 changes: 5 additions & 2 deletions packages/ui/src/hooks/useCount.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ref, createState, createStore, withActions } from "reactivity-store";
import { ref, createState, createStore, withActions, withNamespace } from "reactivity-store";

export const useCount = createState(
withActions(() => ({ count: 0 }), { generateActions: (state) => ({ add: () => state.count++, del: () => state.count-- }) }),
withNamespace(
withActions(() => ({ count: 0 }), { generateActions: (state) => ({ add: () => state.count++, del: () => state.count-- }) }),
{ namespace: "foo", reduxDevTool: true }
),
{ withActions: (s) => ({ add: () => s.count++ }) }
// { withNamespace: "useCount", withActions: (s: { count: number; }) => ({ add: () => s.count++ })}
);
Expand Down

0 comments on commit 6207706

Please sign in to comment.