Skip to content

Commit

Permalink
Move useContext call from hooks to components
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed Oct 22, 2024
1 parent d2e58dd commit 8a1cfd4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 20 deletions.
24 changes: 16 additions & 8 deletions packages/mui-base/src/Tabs/Tab/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import PropTypes from 'prop-types';
import { useTab } from './useTab';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import type { BaseUIComponentProps } from '../../utils/types';
import { TabsOrientation } from '../Root/TabsRoot';
import type { TabsOrientation } from '../Root/TabsRoot';
import { useTabsRootContext } from '../Root/TabsRootContext';

/**
*
Expand All @@ -20,18 +21,25 @@ const Tab = React.forwardRef(function Tab(
props: Tab.Props,
forwardedRef: React.ForwardedRef<Element>,
) {
const { className, disabled = false, render, value, ...other } = props;
const { className, disabled = false, render, value: valueProp, ...other } = props;

const { selected, getRootProps, orientation } = useTab({
const { value: selectedValue, getTabPanelId, orientation } = useTabsRootContext();

const { selected, getRootProps } = useTab({
...props,
getTabPanelId,
isSelected: valueProp === selectedValue,
rootRef: forwardedRef,
});

const ownerState: Tab.OwnerState = {
disabled,
selected,
orientation,
};
const ownerState: Tab.OwnerState = React.useMemo(
() => ({
disabled,
selected,
orientation,
}),
[disabled, selected, orientation],
);

const { renderElement } = useComponentRenderer({
propGetter: getRootProps,
Expand Down
12 changes: 10 additions & 2 deletions packages/mui-base/src/Tabs/Tab/useTab.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ describe('useTab', () => {
it('returns props for root slot', () => {
function TestTab() {
const rootRef = React.createRef<HTMLDivElement>();
const { getRootProps } = useTab({ rootRef });
const { getRootProps } = useTab({
rootRef,
isSelected: true,
getTabPanelId: () => undefined,
});
return <button {...getRootProps()} />;
}

Expand All @@ -37,7 +41,11 @@ describe('useTab', () => {

function TestTab() {
const rootRef = React.createRef<HTMLDivElement>();
const { getRootProps } = useTab({ rootRef });
const { getRootProps } = useTab({
rootRef,
isSelected: true,
getTabPanelId: () => undefined,
});
return (
<button
{...getRootProps({
Expand Down
22 changes: 12 additions & 10 deletions packages/mui-base/src/Tabs/Tab/useTab.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
'use client';
import * as React from 'react';
import { useTabsRootContext } from '../Root/TabsRootContext';
import type { TabsRootContext } from '../Root/TabsRootContext';
import { TabMetadata } from '../Root/useTabsRoot';
import { useCompoundItem } from '../../useCompound';
import { useListItem } from '../../useList';
import { useButton } from '../../useButton';
import { useId } from '../../utils/useId';
import { useForkRef } from '../../utils/useForkRef';
import { mergeReactProps } from '../../utils/mergeReactProps';
import { TabsOrientation } from '../Root/TabsRoot';

function tabValueGenerator(otherTabValues: Set<any>) {
return otherTabValues.size;
}

function useTab(parameters: useTab.Parameters): useTab.ReturnValue {
const { value: valueParam, rootRef: externalRef, disabled = false, id: idParam } = parameters;
const {
value: valueParam,
rootRef: externalRef,
disabled = false,
getTabPanelId,
id: idParam,
isSelected,
} = parameters;

const tabRef = React.useRef<HTMLElement>(null);
const id = useId(idParam);

const { value: selectedValue, getTabPanelId, orientation } = useTabsRootContext();

const tabMetadata = React.useMemo(() => ({ disabled, ref: tabRef, id }), [disabled, tabRef, id]);

const {
Expand All @@ -46,7 +50,6 @@ function useTab(parameters: useTab.Parameters): useTab.ReturnValue {

const getRootProps = React.useCallback(
(externalProps = {}) => {
//
return mergeReactProps<'button'>(
externalProps,
mergeReactProps<'button'>(
Expand All @@ -70,14 +73,13 @@ function useTab(parameters: useTab.Parameters): useTab.ReturnValue {
rootRef: handleRef,
// the `selected` state isn't set on the server (it relies on effects to be calculated),
// so we fall back to checking the `value` prop with the selectedValue from the TabsContext
selected: selected || value === selectedValue,
selected: selected || isSelected,
totalTabsCount,
orientation,
};
}

namespace useTab {
export interface Parameters {
export interface Parameters extends Pick<TabsRootContext, 'getTabPanelId'> {
/**
* The value of the tab.
* It's used to associate the tab with a tab panel(s) with the same value.
Expand All @@ -97,6 +99,7 @@ namespace useTab {
* If not provided, it will be automatically generated.
*/
id?: string;
isSelected: boolean;
/**
* Ref to the root slot's DOM element.
*/
Expand All @@ -116,7 +119,6 @@ namespace useTab {
* 0-based index of the tab in the list of tabs.
*/
index: number;
orientation: TabsOrientation;
/**
* Ref to the root slot's DOM element.
*/
Expand Down

0 comments on commit 8a1cfd4

Please sign in to comment.