Skip to content

Commit

Permalink
[MenuItem][Base] Pass idGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
sai6855 committed May 23, 2023
1 parent 092b06a commit bcdfd0b
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 30 deletions.
6 changes: 5 additions & 1 deletion packages/mui-base/src/useMenuItem/useMenuItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import {
import { useListItem } from '../useList';
import { useCompoundItem } from '../utils/useCompoundItem';

function idGenerator(existingKeys: Set<string>) {
return `menu-item-${existingKeys.size}`;
}

/**
*
* Demos:
Expand Down Expand Up @@ -40,7 +44,7 @@ export default function useMenuItem(params: UseMenuItemParameters): UseMenuItemR
item: id,
});

const { index, totalItemCount } = useCompoundItem(id, itemMetadata);
const { index, totalItemCount } = useCompoundItem(id ?? idGenerator, itemMetadata);

const {
getRootProps: getButtonProps,
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useTab/useTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function useTab(parameters: UseTabParameters): UseTabReturnValue {
id: value,
index,
totalItemCount: totalTabsCount,
} = useCompoundItem<string | number, TabMetadata>(valueParam, tabMetadata, tabValueGenerator);
} = useCompoundItem<string | number, TabMetadata>(valueParam ?? tabValueGenerator, tabMetadata);

const {
getRootProps: getTabProps,
Expand Down
3 changes: 1 addition & 2 deletions packages/mui-base/src/useTabPanel/useTabPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ function useTabPanel(parameters: UseTabPanelParameters): UseTabPanelReturnValue
const id = useId(idParam);

const { id: value } = useCompoundItem<string | number, string | undefined>(
valueParam,
valueParam ?? tabPanelValueGenerator,
id,
tabPanelValueGenerator,
);

const hidden = value !== selectedTabValue;
Expand Down
31 changes: 13 additions & 18 deletions packages/mui-base/src/utils/useCompound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ interface RegisterItemReturnValue<Key> {
deregister: () => void;
}

export type MissingKeyGenerator<Key> = (existingKeys: Set<Key>) => Key;

export type CompoundComponentContextValue<Key, Subitem> = {
/**
* Registers an item with the parent.
* This should be called during the effect phase of the child component.
* The `itemMetadata` should be a stable reference (e.g. a memoized object), to avoid unnecessary re-registrations.
*
* @param id Id of the item.
* @param itemMetadata Arbitrary metadata to pass to the parent component.
* @param missingKeyGenerator A function that generates a unique id for the item.
* @param id Id of the item or A function that generates a unique id for the item.
* It is called with the set of the ids of all the items that have already been registered.
* Return `existingKeys.size` if you want to use the index of the new item as the id.
* Return `existingKeys.size` if you want to use the index of the new item as the id..
* @param itemMetadata Arbitrary metadata to pass to the parent component.
*/
registerItem: (
id: Key | undefined,
id: Key | MissingKeyGenerator<Key> | undefined,
item: Subitem,
missingKeyGenerator?: (existingKeys: Set<Key>) => Key,
) => RegisterItemReturnValue<Key>;
/**
* Returns the 0-based index of the item in the parent component's list of registered items.
Expand Down Expand Up @@ -87,20 +87,15 @@ export function useCompoundParent<Key, Subitem>(): UseCompoundParentReturnValue<
}, []);

const registerItem = React.useCallback(
function registerItem(
id: Key | undefined,
item: Subitem,
missingKeyGenerator?: (existingKeys: Set<Key>) => Key,
) {
function registerItem(id: Key | MissingKeyGenerator<Key> | undefined, item: Subitem) {
let providedOrGeneratedId: Key;
if (id === undefined) {
if (missingKeyGenerator === undefined) {
throw new Error(
"The compound component's child doesn't have a key. You need to provide a missingKeyGenerator to generate it.",
);
}

providedOrGeneratedId = missingKeyGenerator(subitemKeys.current);
throw new Error(
"The compound component's child doesn't have a key. You need to provide a missingKeyGenerator to generate it.",
);
}
if (typeof id === 'function') {
providedOrGeneratedId = (id as MissingKeyGenerator<Key>)(subitemKeys.current);
} else {
providedOrGeneratedId = id;
}
Expand Down
18 changes: 10 additions & 8 deletions packages/mui-base/src/utils/useCompoundItem.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import * as React from 'react';
import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
import { CompoundComponentContext, CompoundComponentContextValue } from './useCompound';
import {
CompoundComponentContext,
CompoundComponentContextValue,
MissingKeyGenerator,
} from './useCompound';

export interface UseCompoundItemReturnValue<Key> {
/**
Expand Down Expand Up @@ -32,18 +36,16 @@ export interface UseCompoundItemReturnValue<Key> {
* @ignore - internal hook.
*/
export function useCompoundItem<Key, Subitem>(
id: Key | undefined,
id: Key | MissingKeyGenerator<Key> | undefined,
itemMetadata: Subitem,
missingKeyGenerator: (existingKeys: Set<Key>) => Key,
): UseCompoundItemReturnValue<Key>;
export function useCompoundItem<Key, Subitem>(
id: Key,
itemMetadata: Subitem,
): UseCompoundItemReturnValue<Key>;
export function useCompoundItem<Key, Subitem>(
id: Key | undefined,
id: Key | MissingKeyGenerator<Key> | undefined,
itemMetadata: Subitem,
missingKeyGenerator?: (existingKeys: Set<Key>) => Key,
): UseCompoundItemReturnValue<Key> {
const context = React.useContext(CompoundComponentContext) as CompoundComponentContextValue<
Key,
Expand All @@ -55,13 +57,13 @@ export function useCompoundItem<Key, Subitem>(
}

const { registerItem } = context;
const [registeredId, setRegisteredId] = React.useState(id);
const [registeredId, setRegisteredId] = React.useState(typeof id === 'function' ? undefined : id);

useEnhancedEffect(() => {
const { id: returnedId, deregister } = registerItem(id, itemMetadata, missingKeyGenerator);
const { id: returnedId, deregister } = registerItem(id, itemMetadata);
setRegisteredId(returnedId);
return deregister;
}, [registerItem, itemMetadata, missingKeyGenerator, id]);
}, [registerItem, itemMetadata, id]);

return {
id: registeredId,
Expand Down

0 comments on commit bcdfd0b

Please sign in to comment.