use first tab as default, use state for tabs and an effect to update

This commit is contained in:
Matthew Russell 2022-03-01 17:40:31 -08:00
parent 5c0d21578f
commit 82cdd245c3
2 changed files with 24 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import React, {
Children,
isValidElement,
ReactNode,
useCallback,
useEffect,
useState,
} from 'react';
@ -131,6 +132,25 @@ interface GridTabsProps {
const GridTabs = ({ children, group }: GridTabsProps) => {
const { query, asPath, replace } = useRouter();
const [activeTab, setActiveTab] = useState<string>(() => {
if (query[group]) {
return query[group];
}
// Default to first tab
return children[0].props.name;
});
// Using replace inside an effect causes a render loop. Seems like its not using useCallback
// eslint-disable-next-line
const safeReplace = useCallback((path: string) => replace(path), []);
useEffect(() => {
const [url, queryString] = asPath.split('?');
const searchParams = new URLSearchParams(queryString);
searchParams.set(group, activeTab as string);
safeReplace(`${url}?${searchParams.toString()}`);
}, [activeTab, group, asPath, safeReplace]);
return (
<div className="h-full grid grid-rows-[min-content_1fr]">
@ -138,7 +158,7 @@ const GridTabs = ({ children, group }: GridTabsProps) => {
<div className="flex gap-[2px] bg-neutral-200" role="tablist">
{Children.map(children, (child) => {
if (!isValidElement(child)) return null;
const isActive = query[group] === child.props.name;
const isActive = activeTab === child.props.name;
const buttonClass = classNames(
'py-4',
'px-12',
@ -152,12 +172,7 @@ const GridTabs = ({ children, group }: GridTabsProps) => {
return (
<button
className={buttonClass}
onClick={() => {
const [url, queryString] = asPath.split('?');
const searchParams = new URLSearchParams(queryString);
searchParams.set(group, child.props.name);
replace(`${url}?${searchParams.toString()}`);
}}
onClick={() => setActiveTab(child.props.name)}
role="tab"
aria-selected={isActive}
aria-controls={`tabpanel-${group}-${child.props.name}`}
@ -171,7 +186,7 @@ const GridTabs = ({ children, group }: GridTabsProps) => {
{/* the content */}
<div className="h-full overflow-auto">
{Children.map(children, (child) => {
if (isValidElement(child) && query[group] === child.props.name) {
if (isValidElement(child) && activeTab === child.props.name) {
return (
<div
role="tabpanel"

View File

@ -1,4 +1,4 @@
import { gql, useQuery } from '@apollo/client';
import { gql } from '@apollo/client';
import { PageQueryContainer } from '../../components/page-query-container';
import Link from 'next/link';
import { useRouter } from 'next/router';