From 09b4c89371f7701ddb465dd403ecb1e38322cbb5 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 20 Sep 2023 21:40:47 +0800 Subject: [PATCH 01/13] Add tests --- .../src/utils/useControllableReducer.test.tsx | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index e6a77bd08eaacb..a02f55987040c2 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -131,6 +131,66 @@ describe('useControllableReducer', () => { setProps({ make: 'Mazda' }); expect(container.firstChild).to.have.text('Mazda 3 (2022)'); }); + + it('warns when a controlled prop becomes uncontrolled', () => { + const reducerParameters: ControllableReducerParameters = { + reducer: (state) => state, + initialState: { make: 'Mazda', model: '3', productionYear: 2022 }, + }; + + function TestComponent(props: { make: string }) { + const [state] = useControllableReducer({ + ...reducerParameters, + controlledProps: { + make: props.make, + }, + }); + return ( +

+ {state.make} {state.model} ({state.productionYear}) +

+ ); + } + + const { container, setProps } = render(); + expect(container.firstChild).to.have.text('Tesla 3 (2022)'); + + expect(() => { + setProps({ make: undefined }); + }).to.toErrorDev( + 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled', + ); + }); + + it('warns when an uncontrolled prop becomes controlled', () => { + const reducerParameters: ControllableReducerParameters = { + reducer: (state) => state, + initialState: { make: 'Mazda', model: '3', productionYear: 2022 }, + }; + + function TestComponent(props: { make: string }) { + const [state] = useControllableReducer({ + ...reducerParameters, + controlledProps: { + make: props.make, + }, + }); + return ( +

+ {state.make} {state.model} ({state.productionYear}) +

+ ); + } + + const { container, setProps } = render(); + expect(container.firstChild).to.have.text('Mazda 3 (2022)'); + + expect(() => { + setProps({ make: 'Tesla' }); + }).to.toErrorDev( + 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + ); + }); }); describe('param: stateComparers', () => { From 6287ff9d50c89e67d2822540a742d8946fc35fd0 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 20 Sep 2023 22:28:36 +0800 Subject: [PATCH 02/13] Add a test for Select --- packages/mui-base/src/Select/Select.test.tsx | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 8176e390991024..1ce251a1198017 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1352,4 +1352,34 @@ describe(' + + + , + ); + + expect(() => { + setProps({ value: undefined }); + }).toErrorDev('MUI: useControllableReducer is changing a controlled prop to be uncontrolled'); + }); + + it('should warn when switching between uncontrolled to controlled', () => { + const { setProps } = render( + , + ); + + expect(() => { + setProps({ value: 1 }); + }).toErrorDev( + 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + ); + }); + }); }); From f90c026fd9e066ada413cf79ecbc34b21943d97a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 20 Sep 2023 22:34:55 +0800 Subject: [PATCH 03/13] Add warning when switching between controlled and uncontrolled --- .../src/utils/useControllableReducer.test.tsx | 2 +- .../src/utils/useControllableReducer.ts | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index a02f55987040c2..76f0fe30f0241d 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -168,7 +168,7 @@ describe('useControllableReducer', () => { initialState: { make: 'Mazda', model: '3', productionYear: 2022 }, }; - function TestComponent(props: { make: string }) { + function TestComponent(props: { make?: string }) { const [state] = useControllableReducer({ ...reducerParameters, controlledProps: { diff --git a/packages/mui-base/src/utils/useControllableReducer.ts b/packages/mui-base/src/utils/useControllableReducer.ts index 790719a937279b..c5abfaca0c5ba3 100644 --- a/packages/mui-base/src/utils/useControllableReducer.ts +++ b/packages/mui-base/src/utils/useControllableReducer.ts @@ -156,6 +156,33 @@ export function useControllableReducer< actionContext, } = parameters; + const controlledPropsRef = React.useRef(controlledProps); + + if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line react-hooks/rules-of-hooks + React.useEffect(() => { + Object.keys(controlledProps).forEach((key) => { + if ( + (controlledPropsRef.current as Record)[key] !== undefined && + (controlledProps as Record)[key] === undefined + ) { + console.error( + 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled', + ); + } + + if ( + (controlledPropsRef.current as Record)[key] === undefined && + (controlledProps as Record)[key] !== undefined + ) { + console.error( + 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + ); + } + }); + }, [controlledProps]); + } + // The reducer that is passed to React.useReducer is wrapped with a function that augments the state with controlled values. const reducerWithControlledState = React.useCallback( (state: State, action: ActionWithContext) => { From 04fa0a8580f7777141660ee186d34753a394a388 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Thu, 12 Oct 2023 15:11:48 +0800 Subject: [PATCH 04/13] Fix useTab test --- packages/mui-base/src/useTab/useTab.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mui-base/src/useTab/useTab.test.tsx b/packages/mui-base/src/useTab/useTab.test.tsx index 829dfd1a175670..c20252849006af 100644 --- a/packages/mui-base/src/useTab/useTab.test.tsx +++ b/packages/mui-base/src/useTab/useTab.test.tsx @@ -18,7 +18,7 @@ describe('useTab', () => { function Test() { return ( - + @@ -43,7 +43,7 @@ describe('useTab', () => { function Test() { return ( - + From b2b5ec38085d5ab95917f41e6889df30b23b167b Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 16:03:02 +0800 Subject: [PATCH 05/13] Update the message --- packages/mui-base/src/Select/Select.test.tsx | 6 ++++-- packages/mui-base/src/utils/useControllableReducer.test.tsx | 4 ++-- packages/mui-base/src/utils/useControllableReducer.ts | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 1ce251a1198017..3e9fdeb6565078 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1364,7 +1364,9 @@ describe('', () => { expect(() => { setProps({ value: 1 }); }).toErrorDev( - 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled: selectedValues', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index 76f0fe30f0241d..cd4370008ca155 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -158,7 +158,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: undefined }); }).to.toErrorDev( - 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled', + 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled: make', ); }); @@ -188,7 +188,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: 'Tesla' }); }).to.toErrorDev( - 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled: make', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.ts b/packages/mui-base/src/utils/useControllableReducer.ts index c5abfaca0c5ba3..e67b000c249098 100644 --- a/packages/mui-base/src/utils/useControllableReducer.ts +++ b/packages/mui-base/src/utils/useControllableReducer.ts @@ -167,7 +167,7 @@ export function useControllableReducer< (controlledProps as Record)[key] === undefined ) { console.error( - 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled', + `MUI: useControllableReducer is changing a controlled prop to be uncontrolled: ${key}`, ); } @@ -176,7 +176,7 @@ export function useControllableReducer< (controlledProps as Record)[key] !== undefined ) { console.error( - 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled', + `MUI: useControllableReducer is changing an uncontrolled prop to be controlled: ${key}`, ); } }); From b05474b98968a959dfc1f7e234022e65e1e5250c Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 16:14:20 +0800 Subject: [PATCH 06/13] Update message --- packages/mui-base/src/Select/Select.test.tsx | 4 ++-- .../mui-base/src/utils/useControllableReducer.test.tsx | 4 ++-- packages/mui-base/src/utils/useControllableReducer.ts | 7 ++++--- .../mui-base/src/utils/useControllableReducer.types.ts | 5 +++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 3e9fdeb6565078..2eee034e95b560 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1365,7 +1365,7 @@ describe('', () => { expect(() => { setProps({ value: 1 }); }).toErrorDev( - 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled: selectedValues', + 'MUI: A component: useControllableReducer is changing an uncontrolled prop to be controlled: selectedValues', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index cd4370008ca155..c8b2a0b31b6bb8 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -158,7 +158,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: undefined }); }).to.toErrorDev( - 'MUI: useControllableReducer is changing a controlled prop to be uncontrolled: make', + 'MUI: A component: useControllableReducer is changing a controlled prop to be uncontrolled: make', ); }); @@ -188,7 +188,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: 'Tesla' }); }).to.toErrorDev( - 'MUI: useControllableReducer is changing an uncontrolled prop to be controlled: make', + 'MUI: A component: useControllableReducer is changing an uncontrolled prop to be controlled: make', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.ts b/packages/mui-base/src/utils/useControllableReducer.ts index e67b000c249098..9d46027535b198 100644 --- a/packages/mui-base/src/utils/useControllableReducer.ts +++ b/packages/mui-base/src/utils/useControllableReducer.ts @@ -154,6 +154,7 @@ export function useControllableReducer< stateComparers = EMPTY_OBJECT, onStateChange = NOOP, actionContext, + componentName = 'useControllableReducer', } = parameters; const controlledPropsRef = React.useRef(controlledProps); @@ -167,7 +168,7 @@ export function useControllableReducer< (controlledProps as Record)[key] === undefined ) { console.error( - `MUI: useControllableReducer is changing a controlled prop to be uncontrolled: ${key}`, + `MUI: A component: ${componentName} is changing a controlled prop to be uncontrolled: ${key}`, ); } @@ -176,11 +177,11 @@ export function useControllableReducer< (controlledProps as Record)[key] !== undefined ) { console.error( - `MUI: useControllableReducer is changing an uncontrolled prop to be controlled: ${key}`, + `MUI: A component: ${componentName} is changing an uncontrolled prop to be controlled: ${key}`, ); } }); - }, [controlledProps]); + }, [controlledProps, componentName]); } // The reducer that is passed to React.useReducer is wrapped with a function that augments the state with controlled values. diff --git a/packages/mui-base/src/utils/useControllableReducer.types.ts b/packages/mui-base/src/utils/useControllableReducer.types.ts index c4769af6c32ae9..e8883082e2d33c 100644 --- a/packages/mui-base/src/utils/useControllableReducer.types.ts +++ b/packages/mui-base/src/utils/useControllableReducer.types.ts @@ -55,6 +55,11 @@ export interface ControllableReducerParameters< * Additional properties that will be added to the action. */ actionContext?: ActionContext; + /** + * The name of the component using useControllableReducer. + * For debugging purposes. + */ + componentName?: string; } /* From a14c35fbcf67a8a6330d66320edacbaaba4f5c20 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 17:32:09 +0800 Subject: [PATCH 07/13] Update params --- packages/mui-base/src/Select/Select.test.tsx | 4 ++-- packages/mui-base/src/useList/useList.ts | 2 ++ packages/mui-base/src/useList/useList.types.ts | 6 ++++++ packages/mui-base/src/useSelect/useSelect.ts | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 2eee034e95b560..9c47903f69aedb 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1365,7 +1365,7 @@ describe('', () => { expect(() => { setProps({ value: 1 }); }).toErrorDev( - 'MUI: A component: useControllableReducer is changing an uncontrolled prop to be controlled: selectedValues', + 'MUI: A component: useSelect is changing an uncontrolled prop to be controlled: selectedValues', ); }); }); diff --git a/packages/mui-base/src/useList/useList.ts b/packages/mui-base/src/useList/useList.ts index d069631a7a9280..6d44beef22dbd8 100644 --- a/packages/mui-base/src/useList/useList.ts +++ b/packages/mui-base/src/useList/useList.ts @@ -90,6 +90,7 @@ function useList< reducerActionContext = EMPTY_OBJECT as CustomActionContext, selectionMode = 'single', stateReducer: externalReducer, + componentName = 'useList', } = params; if (process.env.NODE_ENV !== 'production') { @@ -221,6 +222,7 @@ function useList< controlledProps, stateComparers, onStateChange: handleStateChange, + componentName, }); const { highlightedValue, selectedValues } = state; diff --git a/packages/mui-base/src/useList/useList.types.ts b/packages/mui-base/src/useList/useList.types.ts index 0bd41eeabd4014..33c12b4386ffa6 100644 --- a/packages/mui-base/src/useList/useList.types.ts +++ b/packages/mui-base/src/useList/useList.types.ts @@ -215,6 +215,12 @@ export interface UseListParameters< ListActionContext & CustomActionContext >, ) => State; + /** + * The name of the component using useList. + * For debugging purposes. + * @default 'useList' + */ + componentName?: string; } export interface ListItemState { diff --git a/packages/mui-base/src/useSelect/useSelect.ts b/packages/mui-base/src/useSelect/useSelect.ts index c56af99326db97..7964d0e894128f 100644 --- a/packages/mui-base/src/useSelect/useSelect.ts +++ b/packages/mui-base/src/useSelect/useSelect.ts @@ -287,6 +287,7 @@ function useSelect( getItemAsString: stringifyOption, selectionMode: multiple ? 'multiple' : 'single', stateReducer: selectReducer, + componentName: 'useSelect', }; const { From bf7b9c1d2e7badcb5a74b204599f8195c68fa8f5 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 17:47:24 +0800 Subject: [PATCH 08/13] Update message and params --- packages/mui-base/src/Select/Select.test.tsx | 4 ++-- .../mui-base/src/utils/useControllableReducer.test.tsx | 4 ++-- packages/mui-base/src/utils/useControllableReducer.ts | 10 +++++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 9c47903f69aedb..3dba6419fcb322 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1365,7 +1365,7 @@ describe('', () => { expect(() => { setProps({ value: 1 }); }).toErrorDev( - 'MUI: A component: useSelect is changing an uncontrolled prop to be controlled: selectedValues', + 'useControllableReducer: The useSelect component is changing an uncontrolled prop to be controlled: selectedValues', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index c8b2a0b31b6bb8..ba04914d394f9c 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -158,7 +158,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: undefined }); }).to.toErrorDev( - 'MUI: A component: useControllableReducer is changing a controlled prop to be uncontrolled: make', + 'useControllableReducer: A component is changing a controlled prop to be uncontrolled: make', ); }); @@ -188,7 +188,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: 'Tesla' }); }).to.toErrorDev( - 'MUI: A component: useControllableReducer is changing an uncontrolled prop to be controlled: make', + 'useControllableReducer: A component is changing an uncontrolled prop to be controlled: make', ); }); }); diff --git a/packages/mui-base/src/utils/useControllableReducer.ts b/packages/mui-base/src/utils/useControllableReducer.ts index 9d46027535b198..544a46e84a066e 100644 --- a/packages/mui-base/src/utils/useControllableReducer.ts +++ b/packages/mui-base/src/utils/useControllableReducer.ts @@ -154,7 +154,7 @@ export function useControllableReducer< stateComparers = EMPTY_OBJECT, onStateChange = NOOP, actionContext, - componentName = 'useControllableReducer', + componentName = '', } = parameters; const controlledPropsRef = React.useRef(controlledProps); @@ -168,7 +168,9 @@ export function useControllableReducer< (controlledProps as Record)[key] === undefined ) { console.error( - `MUI: A component: ${componentName} is changing a controlled prop to be uncontrolled: ${key}`, + `useControllableReducer: ${ + componentName ? `The ${componentName} component` : 'A component' + } is changing a controlled prop to be uncontrolled: ${key}`, ); } @@ -177,7 +179,9 @@ export function useControllableReducer< (controlledProps as Record)[key] !== undefined ) { console.error( - `MUI: A component: ${componentName} is changing an uncontrolled prop to be controlled: ${key}`, + `useControllableReducer: ${ + componentName ? `The ${componentName} component` : 'A component' + } is changing an uncontrolled prop to be controlled: ${key}`, ); } }); From 23f6083946beed66d4488681447161de975becae Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 18:16:33 +0800 Subject: [PATCH 09/13] Update message and params again --- packages/mui-base/src/Select/Select.test.tsx | 4 ++-- packages/mui-base/src/Select/Select.tsx | 1 + packages/mui-base/src/useSelect/useSelect.ts | 3 ++- packages/mui-base/src/useSelect/useSelect.types.ts | 6 ++++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/mui-base/src/Select/Select.test.tsx b/packages/mui-base/src/Select/Select.test.tsx index 3dba6419fcb322..f9869c32547d63 100644 --- a/packages/mui-base/src/Select/Select.test.tsx +++ b/packages/mui-base/src/Select/Select.test.tsx @@ -1365,7 +1365,7 @@ describe('', () => { expect(() => { setProps({ value: 1 }); }).toErrorDev( - 'useControllableReducer: The useSelect component is changing an uncontrolled prop to be controlled: selectedValues', + 'useControllableReducer: The Select component is changing an uncontrolled prop to be controlled: selectedValues', ); }); }); diff --git a/packages/mui-base/src/Select/Select.tsx b/packages/mui-base/src/Select/Select.tsx index e43968bd4eccfc..7b250dd7e733d3 100644 --- a/packages/mui-base/src/Select/Select.tsx +++ b/packages/mui-base/src/Select/Select.tsx @@ -144,6 +144,7 @@ const Select = React.forwardRef(function Select< onOpenChange: onListboxOpenChange, getOptionAsString, value: valueProp, + componentName: 'Select', }); const ownerState: SelectOwnerState = { diff --git a/packages/mui-base/src/useSelect/useSelect.ts b/packages/mui-base/src/useSelect/useSelect.ts index 7964d0e894128f..abc9d52240fdf5 100644 --- a/packages/mui-base/src/useSelect/useSelect.ts +++ b/packages/mui-base/src/useSelect/useSelect.ts @@ -101,6 +101,7 @@ function useSelect( getOptionAsString = defaultOptionStringifier, getSerializedValue = defaultFormValueProvider, value: valueProp, + componentName = 'useSelect', } = props; const buttonRef = React.useRef(null); @@ -287,7 +288,7 @@ function useSelect( getItemAsString: stringifyOption, selectionMode: multiple ? 'multiple' : 'single', stateReducer: selectReducer, - componentName: 'useSelect', + componentName, }; const { diff --git a/packages/mui-base/src/useSelect/useSelect.types.ts b/packages/mui-base/src/useSelect/useSelect.types.ts index 217bd98c3c00fa..b94883b6350ee8 100644 --- a/packages/mui-base/src/useSelect/useSelect.types.ts +++ b/packages/mui-base/src/useSelect/useSelect.types.ts @@ -123,6 +123,12 @@ export interface UseSelectParameters; + /** + * The name of the component using useSelect. + * For debugging purposes. + * @default 'useSelect' + */ + componentName?: string; } interface UseSelectButtonSlotEventHandlers { From 2531a53498b5887c4ad9aacbcb05f95320bfb28a Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 24 Nov 2023 18:40:09 +0800 Subject: [PATCH 10/13] Gen api docs --- docs/pages/base-ui/api/use-select.json | 4 ++++ docs/translations/api-docs/use-select/use-select.json | 3 +++ 2 files changed, 7 insertions(+) diff --git a/docs/pages/base-ui/api/use-select.json b/docs/pages/base-ui/api/use-select.json index 5f4cd6d430a3ac..51f573b1423e3b 100644 --- a/docs/pages/base-ui/api/use-select.json +++ b/docs/pages/base-ui/api/use-select.json @@ -9,6 +9,10 @@ "buttonRef": { "type": { "name": "React.Ref<Element>", "description": "React.Ref<Element>" } }, + "componentName": { + "type": { "name": "string", "description": "string" }, + "default": "'useSelect'" + }, "defaultOpen": { "type": { "name": "boolean", "description": "boolean" }, "default": "false" }, "defaultValue": { "type": { diff --git a/docs/translations/api-docs/use-select/use-select.json b/docs/translations/api-docs/use-select/use-select.json index e083d00f9f7b16..e9c367b8131ece 100644 --- a/docs/translations/api-docs/use-select/use-select.json +++ b/docs/translations/api-docs/use-select/use-select.json @@ -5,6 +5,9 @@ "description": "A function used to determine if two options' values are equal. By default, reference equality is used.
There is a performance impact when using the areOptionsEqual prop (proportional to the number of options). Therefore, it's recommented to use the default reference equality comparison whenever possible." }, "buttonRef": { "description": "The ref of the trigger button element." }, + "componentName": { + "description": "The name of the component using useSelect. For debugging purposes." + }, "defaultOpen": { "description": "If true, the select will be open by default." }, "defaultValue": { "description": "The default selected value. Use when the component is not controlled." From ab90257e3d681a89890d827a67baf03a2bf867b2 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 28 Nov 2023 20:19:27 +0800 Subject: [PATCH 11/13] Update test --- packages/mui-base/src/utils/useControllableReducer.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/mui-base/src/utils/useControllableReducer.test.tsx b/packages/mui-base/src/utils/useControllableReducer.test.tsx index ba04914d394f9c..a6cbde41c2b518 100644 --- a/packages/mui-base/src/utils/useControllableReducer.test.tsx +++ b/packages/mui-base/src/utils/useControllableReducer.test.tsx @@ -144,6 +144,7 @@ describe('useControllableReducer', () => { controlledProps: { make: props.make, }, + componentName: 'TestComponent', }); return (

@@ -158,7 +159,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: undefined }); }).to.toErrorDev( - 'useControllableReducer: A component is changing a controlled prop to be uncontrolled: make', + 'useControllableReducer: The TestComponent component is changing a controlled prop to be uncontrolled: make', ); }); @@ -174,6 +175,7 @@ describe('useControllableReducer', () => { controlledProps: { make: props.make, }, + componentName: 'TestComponent', }); return (

@@ -188,7 +190,7 @@ describe('useControllableReducer', () => { expect(() => { setProps({ make: 'Tesla' }); }).to.toErrorDev( - 'useControllableReducer: A component is changing an uncontrolled prop to be controlled: make', + 'useControllableReducer: The TestComponent component is changing an uncontrolled prop to be controlled: make', ); }); }); From 8738931a2d4a8efe0f4d8ee079dd760b6311b185 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 5 Dec 2023 19:18:23 +0800 Subject: [PATCH 12/13] Add componentName to reducer params for useMenu and useDropdown --- docs/pages/base-ui/api/use-dropdown.json | 4 ++++ docs/pages/base-ui/api/use-menu.json | 4 ++++ docs/translations/api-docs/use-dropdown/use-dropdown.json | 3 +++ docs/translations/api-docs/use-menu/use-menu.json | 3 +++ packages/mui-base/src/Menu/Menu.tsx | 1 + packages/mui-base/src/useDropdown/useDropdown.ts | 3 ++- packages/mui-base/src/useDropdown/useDropdown.types.ts | 6 ++++++ packages/mui-base/src/useMenu/useMenu.ts | 2 ++ packages/mui-base/src/useMenu/useMenu.types.ts | 6 ++++++ packages/mui-material-next/src/Menu/Menu.tsx | 2 ++ 10 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/pages/base-ui/api/use-dropdown.json b/docs/pages/base-ui/api/use-dropdown.json index 0c3d4691bd3bec..72a551c82ee7aa 100644 --- a/docs/pages/base-ui/api/use-dropdown.json +++ b/docs/pages/base-ui/api/use-dropdown.json @@ -1,5 +1,9 @@ { "parameters": { + "componentName": { + "type": { "name": "string", "description": "string" }, + "default": "'useDropdown'" + }, "defaultOpen": { "type": { "name": "boolean", "description": "boolean" } }, "onOpenChange": { "type": { diff --git a/docs/pages/base-ui/api/use-menu.json b/docs/pages/base-ui/api/use-menu.json index 0c6f17b9dfd63e..f117ccfae6e480 100644 --- a/docs/pages/base-ui/api/use-menu.json +++ b/docs/pages/base-ui/api/use-menu.json @@ -1,6 +1,10 @@ { "parameters": { "autoFocus": { "type": { "name": "boolean", "description": "boolean" }, "default": "true" }, + "componentName": { + "type": { "name": "string", "description": "string" }, + "default": "'useMenu'" + }, "disabledItemsFocusable": { "type": { "name": "boolean", "description": "boolean" }, "default": "true" diff --git a/docs/translations/api-docs/use-dropdown/use-dropdown.json b/docs/translations/api-docs/use-dropdown/use-dropdown.json index 5ee4ef4ebaf1c1..636ab4b7827d30 100644 --- a/docs/translations/api-docs/use-dropdown/use-dropdown.json +++ b/docs/translations/api-docs/use-dropdown/use-dropdown.json @@ -1,6 +1,9 @@ { "hookDescription": "", "parametersDescriptions": { + "componentName": { + "description": "The name of the component using useDropdown. For debugging purposes." + }, "defaultOpen": { "description": "If true, the dropdown is initially open." }, "onOpenChange": { "description": "Callback fired when the component requests to be opened or closed." diff --git a/docs/translations/api-docs/use-menu/use-menu.json b/docs/translations/api-docs/use-menu/use-menu.json index cf97ce23dcc386..07e143579e1a60 100644 --- a/docs/translations/api-docs/use-menu/use-menu.json +++ b/docs/translations/api-docs/use-menu/use-menu.json @@ -4,6 +4,9 @@ "autoFocus": { "description": "If true (Default) will focus the highligted item. If you set this prop to false the focus will not be moved inside the Menu component. This has severe accessibility implications and should only be considered if you manage focus otherwise." }, + "componentName": { + "description": "The name of the component using useMenu. For debugging purposes." + }, "disabledItemsFocusable": { "description": "If true, it will be possible to highlight disabled items." }, diff --git a/packages/mui-base/src/Menu/Menu.tsx b/packages/mui-base/src/Menu/Menu.tsx index b5cb6933cebc52..f9defa7cfe6e6b 100644 --- a/packages/mui-base/src/Menu/Menu.tsx +++ b/packages/mui-base/src/Menu/Menu.tsx @@ -50,6 +50,7 @@ const Menu = React.forwardRef(function Menu(''); const [triggerElement, setTriggerElement] = React.useState(null); const lastActionType = React.useRef(null); @@ -43,6 +43,7 @@ export function useDropdown(parameters: UseDropdownParameters = {}) { initialState: defaultOpen ? { open: true } : { open: false }, onStateChange: handleStateChange, reducer: dropdownReducer, + componentName, }); React.useEffect(() => { diff --git a/packages/mui-base/src/useDropdown/useDropdown.types.ts b/packages/mui-base/src/useDropdown/useDropdown.types.ts index 90ef8af1aee6d2..568e784a0a3b30 100644 --- a/packages/mui-base/src/useDropdown/useDropdown.types.ts +++ b/packages/mui-base/src/useDropdown/useDropdown.types.ts @@ -17,6 +17,12 @@ export interface UseDropdownParameters { * This is a controlled counterpart of `defaultOpen`. */ open?: boolean; + /** + * The name of the component using useDropdown. + * For debugging purposes. + * @default 'useDropdown' + */ + componentName?: string; } export interface UseDropdownReturnValue { diff --git a/packages/mui-base/src/useMenu/useMenu.ts b/packages/mui-base/src/useMenu/useMenu.ts index 0e86bd674aabc4..456f34b4ac8483 100644 --- a/packages/mui-base/src/useMenu/useMenu.ts +++ b/packages/mui-base/src/useMenu/useMenu.ts @@ -44,6 +44,7 @@ export function useMenu(parameters: UseMenuParameters = {}): UseMenuReturnValue disabledItemsFocusable = true, disableListWrap = false, autoFocus = true, + componentName = 'useMenu', } = parameters; const rootRef = React.useRef(null); @@ -115,6 +116,7 @@ export function useMenu(parameters: UseMenuParameters = {}): UseMenuReturnValue reducerActionContext, selectionMode: 'none', stateReducer: menuReducer, + componentName, }); useEnhancedEffect(() => { diff --git a/packages/mui-base/src/useMenu/useMenu.types.ts b/packages/mui-base/src/useMenu/useMenu.types.ts index 861e651a0db51a..f9f6bd606963c9 100644 --- a/packages/mui-base/src/useMenu/useMenu.types.ts +++ b/packages/mui-base/src/useMenu/useMenu.types.ts @@ -33,6 +33,12 @@ export interface UseMenuParameters { * The ref to the menu's listbox node. */ listboxRef?: React.Ref; + /** + * The name of the component using useMenu. + * For debugging purposes. + * @default 'useMenu' + */ + componentName?: string; } export interface UseMenuReturnValue { diff --git a/packages/mui-material-next/src/Menu/Menu.tsx b/packages/mui-material-next/src/Menu/Menu.tsx index 0911d65102ce72..8ef8fdfae3cd1e 100644 --- a/packages/mui-material-next/src/Menu/Menu.tsx +++ b/packages/mui-material-next/src/Menu/Menu.tsx @@ -114,6 +114,7 @@ const MenuInner = React.forwardRef(function Menu(inProps, ref) { disabledItemsFocusable: Boolean(disabledItemsFocusable), disableListWrap: Boolean(disableListWrap), autoFocus, + componentName: 'Menu', }); const ownerState = { @@ -302,6 +303,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) { const { contextValue: dropdownContextValue } = useDropdown({ open, + componentName: 'Menu', }); return !upperDropdownContext ? ( From 2f01b0176171ce3ef2e4295a1eb4b2e73b5b03f1 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 5 Dec 2023 19:46:41 +0800 Subject: [PATCH 13/13] Fix material-next Menu test --- packages/mui-material-next/src/Menu/Menu.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-material-next/src/Menu/Menu.test.tsx b/packages/mui-material-next/src/Menu/Menu.test.tsx index 8671323165e063..5aa5a057c42c28 100644 --- a/packages/mui-material-next/src/Menu/Menu.test.tsx +++ b/packages/mui-material-next/src/Menu/Menu.test.tsx @@ -218,7 +218,7 @@ describe('

', () => { it('should not focus list if autoFocus=false', () => { const { setProps } = render( - +
, );