RoutedTabs.tsx 2.15 KB
Newer Older
贾浩@五瓣科技's avatar
贾浩@五瓣科技 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
import type { ChakraProps, ThemingProps } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react';
import _pickBy from 'lodash/pickBy';
import { useRouter } from 'next/router';
import React, { useEffect, useRef } from 'react';

import type { RoutedTab } from './types';

import TabsWithScroll from './TabsWithScroll';
import useTabIndexFromQuery from './useTabIndexFromQuery';

interface Props extends ThemingProps<'Tabs'> {
  tabs: Array<RoutedTab>;
  tabListProps?: ChakraProps | (({ isSticky, activeTabIndex }: { isSticky: boolean; activeTabIndex: number }) => ChakraProps);
  rightSlot?: React.ReactNode;
  rightSlotProps?: ChakraProps;
  stickyEnabled?: boolean;
  className?: string;
  onTabChange?: (index: number) => void;
}

const RoutedTabs = ({ tabs, tabListProps, rightSlot, rightSlotProps, stickyEnabled, className, onTabChange, ...themeProps }: Props) => {
  const router = useRouter();
  const tabIndex = useTabIndexFromQuery(tabs);
  const tabsRef = useRef<HTMLDivElement>(null);

  const handleTabChange = React.useCallback((index: number) => {
    const nextTab = tabs[index];

    const queryForPathname = _pickBy(router.query, (value, key) => router.pathname.includes(`[${ key }]`));
    router.push(
      { pathname: router.pathname, query: { ...queryForPathname, tab: nextTab.id } },
      undefined,
      { shallow: true },
    );

    onTabChange?.(index);
  }, [ tabs, router, onTabChange ]);

  useEffect(() => {
    if (router.query.scroll_to_tabs) {
      tabsRef?.current?.scrollIntoView(true);
      delete router.query.scroll_to_tabs;
      router.push(
        {
          pathname: router.pathname,
          query: router.query,
        },
        undefined,
        { shallow: true },
      );
    }
  // replicate componentDidMount
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <TabsWithScroll
      tabs={ tabs }
      tabListProps={ tabListProps }
      rightSlot={ rightSlot }
      rightSlotProps={ rightSlotProps }
      stickyEnabled={ stickyEnabled }
      onTabChange={ handleTabChange }
      defaultTabIndex={ tabIndex }
      { ...themeProps }
    />
  );
};

export default React.memo(chakra(RoutedTabs));