From 2e3ba0be858efa20d98e612aa8c5bd3155dcf6dd Mon Sep 17 00:00:00 2001 From: MrWangJustToDo <2711470541@qq.com> Date: Mon, 18 Nov 2024 11:21:27 +0800 Subject: [PATCH] update --- packages/r-store/package.json | 2 +- packages/r-store/src/shared/controller.ts | 12 ++++++++++-- packages/r-store/src/shared/hook.ts | 4 +++- packages/r-store/src/shared/lifeCycle.ts | 3 +++ packages/r-store/src/state/_internal.ts | 4 ++++ packages/r-store/src/state/tools.ts | 13 +++++++++---- 6 files changed, 30 insertions(+), 8 deletions(-) diff --git a/packages/r-store/package.json b/packages/r-store/package.json index 1b42a63..389978e 100644 --- a/packages/r-store/package.json +++ b/packages/r-store/package.json @@ -1,6 +1,6 @@ { "name": "reactivity-store", - "version": "0.3.7", + "version": "0.3.8", "author": "MrWangJustToDo", "license": "MIT", "description": "a reactive store, make you write reactive logic in react app just like zustand", diff --git a/packages/r-store/src/shared/controller.ts b/packages/r-store/src/shared/controller.ts index 87a8dd9..f8a637d 100644 --- a/packages/r-store/src/shared/controller.ts +++ b/packages/r-store/src/shared/controller.ts @@ -54,6 +54,8 @@ export class Controller { _effect: ReactiveEffect; + _state: T; + _devState: any; _devSelector: any; @@ -133,10 +135,16 @@ export class Controller { }; _scheduler = () => { - this.run(); + const newState = this.run(); if (!this._isActive) return; + const triggerUpdate = this._lifeCycle.triggerUpdateOnlyChanged ? !Object.is(newState, this._state) : true; + + if (!triggerUpdate) return; + + this._state = newState; + if (this._lifeCycle.canUpdateComponent) { if (this._lifeCycle.syncUpdateComponent) { this.notify(); @@ -170,7 +178,7 @@ export class Controller { // TODO move into constructor function? run() { - this._effect.run(); + return this._effect.run(); } stop() { diff --git a/packages/r-store/src/shared/hook.ts b/packages/r-store/src/shared/hook.ts index bf00262..1cf2689 100644 --- a/packages/r-store/src/shared/hook.ts +++ b/packages/r-store/src/shared/hook.ts @@ -99,7 +99,7 @@ export const createHook = , C extends Record> & C) => P) => { + function useReactiveHookWithSelector (selector?: (state: DeepReadonly> & C) => P) { const ref = useRef

>>(); const selectorRef = useSubscribeCallbackRef(selector, currentIsDeep); @@ -174,6 +174,8 @@ export const createHook = , C extends Record ({ hasHookInstall: false, canUpdateComponent: true, syncUpdateComponent: false, + triggerUpdateOnlyChanged: false, }); diff --git a/packages/r-store/src/state/_internal.ts b/packages/r-store/src/state/_internal.ts index 2899ede..bd4e6e8 100644 --- a/packages/r-store/src/state/_internal.ts +++ b/packages/r-store/src/state/_internal.ts @@ -103,6 +103,10 @@ export function internalCreateState, P extends const stableSelector = selectorOptions?.stableSelector ?? false; + const triggerUpdateOnlyChanged = selectorOptions?.triggerUpdateOnlyChanged ?? false; + + lifeCycle.triggerUpdateOnlyChanged = triggerUpdateOnlyChanged; + if (__DEV__ && reduxDevTool) { actions = connectDevTool(namespaceOptions.namespace, actions, rawState, reactiveState, namespaceOptions) as P; } diff --git a/packages/r-store/src/state/tools.ts b/packages/r-store/src/state/tools.ts index 8a497c1..9f7c00f 100644 --- a/packages/r-store/src/state/tools.ts +++ b/packages/r-store/src/state/tools.ts @@ -79,6 +79,11 @@ export type WithNamespaceProps = { export type WithSelectorOptionsProps = { deepSelector?: boolean; stableSelector?: boolean; + /** + * state what return from the selector will be used to compare with the previous state, if the state is equal, the component will not update + * @default false + */ + triggerUpdateOnlyChanged?: boolean; }; /** @@ -134,18 +139,18 @@ export const getFinalActions = , P extends Rec */ export const getFinalNamespace = , P extends Record>(state: MaybeStateWithMiddleware) => { if (state["$$__state__$$"]) - return (state["$$__namespace__$$"] || {}) as { namespace?: string; reduxDevTool?: boolean; listener?: (state: any) => any; shallow?: boolean }; + return (state["$$__namespace__$$"] || {}) as WithNamespaceProps; - return {} as { namespace?: string; reduxDevTool?: boolean; listener?: (state: any) => any; shallow?: boolean }; + return {} as WithNamespaceProps; }; /** * @internal */ export const getFinalSelectorOptions = , P extends Record>(state: MaybeStateWithMiddleware) => { - if (state["$$__state__$$"]) return (state["$$__selectorOptions__$$"] || {}) as { deepSelector?: boolean; stableSelector?: boolean }; + if (state["$$__state__$$"]) return (state["$$__selectorOptions__$$"] || {}) as WithSelectorOptionsProps; - return {} as { deepSelector?: boolean; stableSelector?: boolean }; + return {} as WithSelectorOptionsProps; }; // function for help to build external middleware