//types/types.ts
export interface Component {
id: string;
category: Category;
tag: Tag;
name: string;
desc: string;
image: Image;
}
export interface Image {
id: string;
url: string;
}
export interface Category {
slug: string;
title: string;
}
export interface Tag {
slug: string;
title: string;
}
//Filter/filter.tsx
"use client";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { Category, Tag } from "@/types/types";
import { useSearchParams, useRouter } from "next/navigation";
import qs from "query-string";
import React from "react";
interface Props {
data: (Category | Tag)[];
name: string;
valueKey: string;
}
const Filter = ({ data, name, valueKey }: Props) => {
const searchParams = useSearchParams();
const router = useRouter();
const selectedValue = searchParams.get(valueKey);
const onClick = (slug: string) => {
const current = qs.parse(searchParams.toString());
const query = {
...current,
[valueKey]: slug,
};
if (current[valueKey] === slug) {
query[valueKey] = null;
}
const url = qs.stringifyUrl(
{
url: window.location.href,
query,
},
{ skipNull: true }
);
router.push(url);
};
return (
<div className="mb-8">
<h3 className="text-lg font-semibold">{name}</h3>
<hr className="my-4" />
<div className="flex flex-wrap gap-2">
{data.map((filter: any) => (
<div key={filter.slug} className="flex items-center">
<Button
size="sm"
className={cn(
"rounded-md text-sm text-gray-800 bg-white border border-gray-300 shadow-
none",
selectedValue === filter.slug && "bg-black text-white"
)}
onClick={() => onClick(filter.slug)}
>
{filter.title}
</Button>
</div>
))}
</div>
</div>
);
};
export default Filter;
//Filter/filters.tsx
export const revalidate = 0;
import Filter from "@/components/elements/Filter/filter";
import { getComponentCategory, getTag } from "@/sanity/queries/page";
import React from "react";
type Props = {
params?: {
componentId: string;
};
searchParams?: {
category: string;
tag: string;
};
};
export const Filters = async ({ params, searchParams }: Props) => {
const categories = await getComponentCategory();
const tags = await getTag();
return (
<div className="px-4 sm:px-6 lg:px-8 pb-24">
<div className="lg:grid lg:grid-cols-5 lg:gap-x-8">
<div className="hidden lg:block">
<Filter valueKey="category" name="Categories" data={categories} />
<Filter valueKey="tag" name="Tags" data={tags} />
</div>
</div>
</div>
);
};
//mobile-menu/mobile-menu.tsx
"use client";
import { Button } from "@/components/ui/button";
import { ArrowLeftToLine, SlidersHorizontal } from "lucide-react";
import React, { useState } from "react";
type Props = {
children: React.ReactNode;
};
const MobileNav = ({ children }: Props) => {
const [showMenu, setShowMenu] = useState(false);
const toggleMenu = () => {
setShowMenu((prev) => !prev);
};
return (
<div>
<Button
variant="outline"
size="sm"
className="font-medium text-slate-800/90"
onClick={() => toggleMenu()}
>
<SlidersHorizontal className="w-4 h-4 mr-2 relative" />
Filters
</Button>
<div>
{showMenu ? (
<div className="absolute z-10 bg-white w-[17.5rem] top-0 left-0 flex flex-col
py-2 border-r min-h-screen">
<div className="border-b pb-2">
<div className="flex items-center justify-between px-4">
<h3 className="flex items-center">
<SlidersHorizontal className="w-4 h-4 mr-2" />
Filters
</h3>
<Button
variant="ghost"
size="sm"
className=""
onClick={() => toggleMenu()}
>
<ArrowLeftToLine className="w-4 h-4" />
</Button>
</div>
</div>
<div>{children}</div>
</div>
) : null}
</div>
</div>
);
};
export default MobileNav;
//filterbar/filterbar.tsx
"use client";
import React, { useState } from "react";
import MobileNav from "@/components/layouts/mobile-menu/mobile-menu";
import { Filters } from "../Filter/filters";
type Props = {};
export const Filterbar = (props: Props) => {
const [position, setPosition] = useState("bottom");
return (
<div className="relative flex items-center justify-between w-full px-4 md:px-10 py-
2">
<MobileNav>
<Filters />
</MobileNav>
</div>
);
};
I am building a Nextjs app, and when I want to render the Filters component inside of MobileNav, the toggle of MobileNav does not work, hence the children cannot be seen. If for example I render something else inside the MobileNav, everything seems to be working just fine. I do not get any async/await being used inside a server component error
Your help will be welcome and appreciated. Thanks in advance.