From 3022be8362203b5ecacf712a502cbb7fb0ee4211 Mon Sep 17 00:00:00 2001 From: Bernardo Sunderhus Date: Wed, 10 May 2023 12:01:08 +0000 Subject: [PATCH 1/2] chore: defers useControllableState state to initializer method --- ...ities-3e7e29b4-ccde-4269-ac7f-8adf2333171e.json | 7 +++++++ .../src/hooks/useControllableState.ts | 14 +++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 change/@fluentui-react-utilities-3e7e29b4-ccde-4269-ac7f-8adf2333171e.json diff --git a/change/@fluentui-react-utilities-3e7e29b4-ccde-4269-ac7f-8adf2333171e.json b/change/@fluentui-react-utilities-3e7e29b4-ccde-4269-ac7f-8adf2333171e.json new file mode 100644 index 00000000000000..24466911ead6db --- /dev/null +++ b/change/@fluentui-react-utilities-3e7e29b4-ccde-4269-ac7f-8adf2333171e.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "feat: defers useControllableState state to initializer method", + "packageName": "@fluentui/react-utilities", + "email": "bernardo.sunderhus@gmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-utilities/src/hooks/useControllableState.ts b/packages/react-components/react-utilities/src/hooks/useControllableState.ts index 6e47b1c1e8bde5..962ff558aa93ad 100644 --- a/packages/react-components/react-utilities/src/hooks/useControllableState.ts +++ b/packages/react-components/react-utilities/src/hooks/useControllableState.ts @@ -39,8 +39,12 @@ export type UseControllableStateOptions = { export const useControllableState = ( options: UseControllableStateOptions, ): [State, React.Dispatch>] => { - const initialState = typeof options.defaultState === 'undefined' ? options.initialState : options.defaultState; - const [internalState, setInternalState] = React.useState(initialState); + const [internalState, setInternalState] = React.useState(() => { + if (options.defaultState === undefined) { + return options.initialState; + } + return isInitializer(options.defaultState) ? options.defaultState() : options.defaultState; + }); return useIsControlled(options.state) ? [options.state, noop] : [internalState, setInternalState]; }; @@ -48,12 +52,16 @@ function noop() { /* noop */ } +function isInitializer(value: Value | (() => Value)): value is () => Value { + return typeof value === 'function'; +} + /** * Helper hook to handle previous comparison of controlled/uncontrolled * Prints an error when isControlled value switches between subsequent renders * @returns - whether the value is controlled */ -const useIsControlled = (controlledValue?: V): controlledValue is V => { +const useIsControlled = (controlledValue: V | undefined): controlledValue is V => { const [isControlled] = React.useState(() => controlledValue !== undefined); if (process.env.NODE_ENV !== 'production') { From ef642a9ea34895f836c60cb412938a1b8cb7637a Mon Sep 17 00:00:00 2001 From: Bernardo Sunderhus Date: Wed, 10 May 2023 14:51:47 +0200 Subject: [PATCH 2/2] Update packages/react-components/react-utilities/src/hooks/useControllableState.ts Co-authored-by: Oleksandr Fediashov --- .../react-utilities/src/hooks/useControllableState.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-components/react-utilities/src/hooks/useControllableState.ts b/packages/react-components/react-utilities/src/hooks/useControllableState.ts index 962ff558aa93ad..af679fd104899b 100644 --- a/packages/react-components/react-utilities/src/hooks/useControllableState.ts +++ b/packages/react-components/react-utilities/src/hooks/useControllableState.ts @@ -48,12 +48,12 @@ export const useControllableState = ( return useIsControlled(options.state) ? [options.state, noop] : [internalState, setInternalState]; }; -function noop() { - /* noop */ +function isInitializer(value: State | (() => State)): value is () => State { + return typeof value === 'function'; } -function isInitializer(value: Value | (() => Value)): value is () => Value { - return typeof value === 'function'; +function noop() { + /* noop */ } /**