diff --git a/dist/cjs/index.js b/dist/cjs/index.js index 29ec6cd..820ff72 100644 --- a/dist/cjs/index.js +++ b/dist/cjs/index.js @@ -90,8 +90,10 @@ var createSelector = function createSelector(_temp) { }; var selector = /*#__PURE__*/createSelector(); -var useSnapshot = function useSnapshot(state) { - return shim.useSyncExternalStore(state.subscribe, state.get, state.get); +var useSnapshot = function useSnapshot(_ref) { + var subscribe = _ref.subscribe, + get = _ref.get; + return shim.useSyncExternalStore(subscribe, get, get); }; exports.createSelector = createSelector; diff --git a/dist/es/react/useSnapshot.js b/dist/es/react/useSnapshot.js index 4d3795e..c63c22d 100644 --- a/dist/es/react/useSnapshot.js +++ b/dist/es/react/useSnapshot.js @@ -1,7 +1,9 @@ import { useSyncExternalStore } from 'use-sync-external-store/shim'; -var useSnapshot = function useSnapshot(state) { - return useSyncExternalStore(state.subscribe, state.get, state.get); +var useSnapshot = function useSnapshot(_ref) { + var subscribe = _ref.subscribe, + get = _ref.get; + return useSyncExternalStore(subscribe, get, get); }; export { useSnapshot }; diff --git a/dist/middleware/cjs/index.js b/dist/middleware/cjs/index.js index 66d9ae5..a43b033 100644 --- a/dist/middleware/cjs/index.js +++ b/dist/middleware/cjs/index.js @@ -65,29 +65,42 @@ var persist = function persist(_temp) { var key = _ref3[0], set = _ref3[1]; var value = getStorage().getItem(key); - value && set(JSON.parse(value), 'HYDRATE'); + value && set(JSON.parse(value), "HYDRATE_" + key); }); states.length = 0; }; return middleware; }; -var reduxDevtools = function reduxDevtools(_ref, config) { - var set = _ref.set, - get = _ref.get; - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return set; - var devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ - name: config == null ? void 0 : config.key +var reduxDevtools = function reduxDevtools(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + name = _ref.name; + var devtoolsExt; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) return function (_ref2) { + var set = _ref2.set; + return set; + }; + var devtools = devtoolsExt.connect({ + name: name }); - devtools.init(get()); - return function (value, action) { - set.apply(null, arguments); - devtools.send(typeof action === 'string' ? { - type: action - } : action || { - type: 'SET', - value: value - }, get()); + var mergedState = {}; + return function (_ref3, config) { + var set = _ref3.set, + get = _ref3.get; + var key = config == null ? void 0 : config.key; + if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` middleware is used.'); + mergedState[key] = get(); + devtools.init(mergedState); + return function (value, action) { + set.apply(null, arguments); + mergedState[key] = get(); + devtools.send(typeof action === 'string' ? { + type: action + } : action || { + type: "SET_" + key, + value: value + }, mergedState); + }; }; }; diff --git a/dist/middleware/es/persist.js b/dist/middleware/es/persist.js index 762d4db..62e463c 100644 --- a/dist/middleware/es/persist.js +++ b/dist/middleware/es/persist.js @@ -23,7 +23,7 @@ var persist = function persist(_temp) { var key = _ref3[0], set = _ref3[1]; var value = getStorage().getItem(key); - value && set(JSON.parse(value), 'HYDRATE'); + value && set(JSON.parse(value), "HYDRATE_" + key); }); states.length = 0; }; diff --git a/dist/middleware/es/reduxDevtools.js b/dist/middleware/es/reduxDevtools.js index bb0e929..de85cd2 100644 --- a/dist/middleware/es/reduxDevtools.js +++ b/dist/middleware/es/reduxDevtools.js @@ -1,19 +1,32 @@ -var reduxDevtools = function reduxDevtools(_ref, config) { - var set = _ref.set, - get = _ref.get; - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return set; - var devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ - name: config == null ? void 0 : config.key +var reduxDevtools = function reduxDevtools(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + name = _ref.name; + var devtoolsExt; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) return function (_ref2) { + var set = _ref2.set; + return set; + }; + var devtools = devtoolsExt.connect({ + name: name }); - devtools.init(get()); - return function (value, action) { - set.apply(null, arguments); - devtools.send(typeof action === 'string' ? { - type: action - } : action || { - type: 'SET', - value: value - }, get()); + var mergedState = {}; + return function (_ref3, config) { + var set = _ref3.set, + get = _ref3.get; + var key = config == null ? void 0 : config.key; + if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` middleware is used.'); + mergedState[key] = get(); + devtools.init(mergedState); + return function (value, action) { + set.apply(null, arguments); + mergedState[key] = get(); + devtools.send(typeof action === 'string' ? { + type: action + } : action || { + type: "SET_" + key, + value: value + }, mergedState); + }; }; }; diff --git a/dist/plugin/cjs/index.js b/dist/plugin/cjs/index.js index 295f50d..d216ad1 100644 --- a/dist/plugin/cjs/index.js +++ b/dist/plugin/cjs/index.js @@ -14,17 +14,29 @@ var applyPlugin = function applyPlugin() { }; }; -var reduxDevtools = function reduxDevtools(_ref, config) { - var get = _ref.get, - subscribe = _ref.subscribe; - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return; - var devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ - name: config == null ? void 0 : config.key - }); - devtools.init(get()); - subscribe(function () { - return devtools.init(get()); +var reduxDevtools = function reduxDevtools(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + name = _ref.name; + var devtoolsExt; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) return function () { + /*do nothing*/ + }; + var devtools = devtoolsExt.connect({ + name: name }); + var mergedState = {}; + return function (_ref2, config) { + var get = _ref2.get, + subscribe = _ref2.subscribe; + var key = config == null ? void 0 : config.key; + if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.'); + var updateState = function updateState() { + mergedState[key] = get(); + devtools.init(mergedState); + }; + updateState(); + subscribe(updateState); + }; }; exports.applyPlugin = applyPlugin; diff --git a/dist/plugin/es/reduxDevtools.js b/dist/plugin/es/reduxDevtools.js index e5163fb..807d2ff 100644 --- a/dist/plugin/es/reduxDevtools.js +++ b/dist/plugin/es/reduxDevtools.js @@ -1,14 +1,26 @@ -var reduxDevtools = function reduxDevtools(_ref, config) { - var get = _ref.get, - subscribe = _ref.subscribe; - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return; - var devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ - name: config == null ? void 0 : config.key - }); - devtools.init(get()); - subscribe(function () { - return devtools.init(get()); +var reduxDevtools = function reduxDevtools(_temp) { + var _ref = _temp === void 0 ? {} : _temp, + name = _ref.name; + var devtoolsExt; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) return function () { + /*do nothing*/ + }; + var devtools = devtoolsExt.connect({ + name: name }); + var mergedState = {}; + return function (_ref2, config) { + var get = _ref2.get, + subscribe = _ref2.subscribe; + var key = config == null ? void 0 : config.key; + if (!key) throw new Error('[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.'); + var updateState = function updateState() { + mergedState[key] = get(); + devtools.init(mergedState); + }; + updateState(); + subscribe(updateState); + }; }; export { reduxDevtools }; diff --git a/examples/examples/counter/Counter.tsx b/examples/examples/counter/Counter.tsx index dede71d..9aebb60 100644 --- a/examples/examples/counter/Counter.tsx +++ b/examples/examples/counter/Counter.tsx @@ -17,7 +17,7 @@ const reducer = (state: number, { type, by = 1 }: { type: ActionTypes; by?: numb const persistMiddleware = persist({ prefix: 'counter-', getStorage: () => sessionStorage }); const counterState = createState({ - middleware: applyMiddleware(persistMiddleware, reduxDevtools) + middleware: applyMiddleware(persistMiddleware, reduxDevtools({ name: 'counterApp-state' })) })( 0, (set, get) => ({ diff --git a/examples/examples/todo/todo.ts b/examples/examples/todo/todo.ts index 8402217..8ca5fef 100644 --- a/examples/examples/todo/todo.ts +++ b/examples/examples/todo/todo.ts @@ -4,7 +4,7 @@ import { reduxDevtools as devtoolsPlugin } from 'reactish-state/plugin'; const persistMiddleware = persist({ prefix: 'todoApp-' }); const state = createState({ - middleware: applyMiddleware(immer, persistMiddleware, reduxDevtools) + middleware: applyMiddleware(immer, persistMiddleware, reduxDevtools({ name: 'todoApp-state' })) }); interface Todo { @@ -33,13 +33,13 @@ const todoListState = state( { type: 'todos/deleteItem', id } ) }), - { key: 'todo-list' } + { key: 'todoList' } ); type VisibilityFilter = 'ALL' | 'COMPLETED' | 'IN_PROGRESS'; const visibilityFilterState = state('IN_PROGRESS' as VisibilityFilter, null, { key: 'filter' }); -const selector = createSelector({ plugin: devtoolsPlugin }); +const selector = createSelector({ plugin: devtoolsPlugin({ name: 'todoApp-selector' }) }); const visibleTodoList = selector( todoListState, visibilityFilterState, @@ -53,7 +53,7 @@ const visibleTodoList = selector( return todoList.filter(({ isCompleted }) => !isCompleted); } }, - { key: 'visible-todos' } + { key: 'visibleTodos' } ); const statsSelector = selector( diff --git a/package-lock.json b/package-lock.json index 38dddd0..aae3409 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "reactish-state", - "version": "0.8.1", + "version": "0.9.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "reactish-state", - "version": "0.8.1", + "version": "0.9.0", "license": "MIT", "dependencies": { "use-sync-external-store": "^1.2.0" diff --git a/package.json b/package.json index ab8cdef..be6e183 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reactish-state", - "version": "0.8.1", + "version": "0.9.0", "description": "", "author": "Zheng Song", "license": "MIT", diff --git a/src/middleware/persist.ts b/src/middleware/persist.ts index d08b947..46fa800 100644 --- a/src/middleware/persist.ts +++ b/src/middleware/persist.ts @@ -30,7 +30,7 @@ const persist: Persist = ({ prefix, getStorage = () => localStorage } = {}) => { middleware.hydrate = () => { states.forEach(([key, set]) => { const value = getStorage().getItem(key); - value && set(JSON.parse(value), 'HYDRATE'); + value && set(JSON.parse(value), `HYDRATE_${key}`); }); states.length = 0; }; diff --git a/src/middleware/reduxDevtools.ts b/src/middleware/reduxDevtools.ts index e60c698..fa489aa 100644 --- a/src/middleware/reduxDevtools.ts +++ b/src/middleware/reduxDevtools.ts @@ -1,18 +1,33 @@ import type {} from '@redux-devtools/extension'; import type { Middleware } from '../common'; -const reduxDevtools: Middleware = ({ set, get }, config) => { - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return set; +type ReduxDevtools = (options?: { name?: string }) => Middleware; - const devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name: config?.key }); - devtools.init(get()); +const reduxDevtools: ReduxDevtools = ({ name } = {}) => { + let devtoolsExt: Window['__REDUX_DEVTOOLS_EXTENSION__']; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) + return ({ set }) => set; - return function (value, action) { - set.apply(null, arguments as unknown as Parameters); - devtools.send( - typeof action === 'string' ? { type: action } : action || { type: 'SET', value }, - get() - ); + const devtools = devtoolsExt.connect({ name }); + const mergedState: { [index: string]: unknown } = {}; + + return ({ set, get }, config) => { + const key = config?.key; + if (!key) + throw new Error( + '[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` middleware is used.' + ); + mergedState[key] = get(); + devtools.init(mergedState); + + return function (value, action) { + set.apply(null, arguments as unknown as Parameters); + mergedState[key] = get(); + devtools.send( + typeof action === 'string' ? { type: action } : action || { type: `SET_${key}`, value }, + mergedState + ); + }; }; }; diff --git a/src/plugin/reduxDevtools.ts b/src/plugin/reduxDevtools.ts index 6c892ea..f9d7262 100644 --- a/src/plugin/reduxDevtools.ts +++ b/src/plugin/reduxDevtools.ts @@ -1,12 +1,33 @@ import type {} from '@redux-devtools/extension'; import type { Plugin } from '../common'; -const reduxDevtools: Plugin = ({ get, subscribe }, config) => { - if (typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) return; +type ReduxDevtools = (options?: { name?: string }) => Plugin; - const devtools = window.__REDUX_DEVTOOLS_EXTENSION__.connect({ name: config?.key }); - devtools.init(get()); - subscribe(() => devtools.init(get())); +const reduxDevtools: ReduxDevtools = ({ name } = {}) => { + let devtoolsExt: Window['__REDUX_DEVTOOLS_EXTENSION__']; + if (typeof window === 'undefined' || !(devtoolsExt = window.__REDUX_DEVTOOLS_EXTENSION__)) + return () => { + /*do nothing*/ + }; + + const devtools = devtoolsExt.connect({ name }); + const mergedState: { [index: string]: unknown } = {}; + + return ({ get, subscribe }, config) => { + const key = config?.key; + if (!key) + throw new Error( + '[reactish-state] state should be provided with a string `key` in the config object when the `reduxDevtools` plugin is used.' + ); + + const updateState = () => { + mergedState[key] = get(); + devtools.init(mergedState); + }; + + updateState(); + subscribe(updateState); + }; }; export { reduxDevtools }; diff --git a/src/react/useSnapshot.ts b/src/react/useSnapshot.ts index 684bd08..06f70c8 100644 --- a/src/react/useSnapshot.ts +++ b/src/react/useSnapshot.ts @@ -1,7 +1,7 @@ import type { Reactish } from '../common'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; -const useSnapshot = (state: Reactish) => - useSyncExternalStore(state.subscribe, state.get, state.get); +const useSnapshot = ({ subscribe, get }: Reactish) => + useSyncExternalStore(subscribe, get, get); export { useSnapshot }; diff --git a/types/middleware/reduxDevtools.d.ts b/types/middleware/reduxDevtools.d.ts index 2282977..9b54bf3 100644 --- a/types/middleware/reduxDevtools.d.ts +++ b/types/middleware/reduxDevtools.d.ts @@ -1,3 +1,6 @@ import type { Middleware } from '../common'; -declare const reduxDevtools: Middleware; +declare type ReduxDevtools = (options?: { + name?: string; +}) => Middleware; +declare const reduxDevtools: ReduxDevtools; export { reduxDevtools }; diff --git a/types/plugin/reduxDevtools.d.ts b/types/plugin/reduxDevtools.d.ts index d5f1df8..aacd9b5 100644 --- a/types/plugin/reduxDevtools.d.ts +++ b/types/plugin/reduxDevtools.d.ts @@ -1,3 +1,6 @@ import type { Plugin } from '../common'; -declare const reduxDevtools: Plugin; +declare type ReduxDevtools = (options?: { + name?: string; +}) => Plugin; +declare const reduxDevtools: ReduxDevtools; export { reduxDevtools }; diff --git a/types/react/useSnapshot.d.ts b/types/react/useSnapshot.d.ts index 2a11b1c..12a41b3 100644 --- a/types/react/useSnapshot.d.ts +++ b/types/react/useSnapshot.d.ts @@ -1,3 +1,3 @@ import type { Reactish } from '../common'; -declare const useSnapshot: (state: Reactish) => T; +declare const useSnapshot: ({ subscribe, get }: Reactish) => T; export { useSnapshot };