-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MenuItem][Base] Pass idGenerator function #37364
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,23 +12,20 @@ interface RegisterItemReturnValue<Key> { | |
deregister: () => void; | ||
} | ||
|
||
export type KeyGenerator<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, | ||
item: Subitem, | ||
missingKeyGenerator?: (existingKeys: Set<Key>) => Key, | ||
) => RegisterItemReturnValue<Key>; | ||
registerItem: (id: Key | KeyGenerator<Key>, item: Subitem) => RegisterItemReturnValue<Key>; | ||
/** | ||
* Returns the 0-based index of the item in the parent component's list of registered items. | ||
* | ||
|
@@ -116,20 +113,11 @@ export function useCompoundParent< | |
}, []); | ||
|
||
const registerItem = React.useCallback( | ||
function registerItem( | ||
id: Key | undefined, | ||
item: Subitem, | ||
missingKeyGenerator?: (existingKeys: Set<Key>) => Key, | ||
) { | ||
function registerItem(id: Key | KeyGenerator<Key>, item: Subitem) { | ||
let providedOrGeneratedId: Key; | ||
if (id === undefined) { | ||
if (missingKeyGenerator === undefined) { | ||
throw new Error( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since |
||
"The compound component's child doesn't have a key. You need to provide a missingKeyGenerator to generate it.", | ||
); | ||
} | ||
|
||
providedOrGeneratedId = missingKeyGenerator(subitemKeys.current); | ||
|
||
if (typeof id === 'function') { | ||
providedOrGeneratedId = (id as KeyGenerator<Key>)(subitemKeys.current); | ||
} else { | ||
providedOrGeneratedId = id; | ||
} | ||
|
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, | ||
KeyGenerator, | ||
} from './useCompound'; | ||
|
||
export interface UseCompoundItemReturnValue<Key> { | ||
/** | ||
|
@@ -31,19 +35,17 @@ export interface UseCompoundItemReturnValue<Key> { | |
* | ||
* @ignore - internal hook. | ||
*/ | ||
export function useCompoundItem<Key, Subitem extends { ref: React.RefObject<Node> }>( | ||
id: Key | undefined, | ||
export function useCompoundItem<Key, Subitem>( | ||
id: Key | KeyGenerator<Key>, | ||
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 | KeyGenerator<Key>, | ||
itemMetadata: Subitem, | ||
missingKeyGenerator?: (existingKeys: Set<Key>) => Key, | ||
): UseCompoundItemReturnValue<Key> { | ||
const context = React.useContext(CompoundComponentContext) as CompoundComponentContextValue< | ||
Key, | ||
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since parameter to pass to the |
||
|
||
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, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really sure how to test that if this function is being called or not as this function runs only on react versions less than 18.