Dynamic Filtering items with prisma and Nextjs?
Oi everyone! I use prisma in combination with Nextjs and mongodb on a project that deals with animal adoption. Namely, now I would like to do dynamic filtering by certain categories and enable it to interact with the user on the client side. Well, I'm interested in whether it's feasible to do it using prism, since I found out through the documentation that I can filter out certain things via the
where: { }
query.
Any help and suggestions on how to do this are welcome. Thank you all!50 Replies
yeah, you can @tom_bombadil
I can recommend best libraries for your case
https://nuqs.47ng.com/
this library will be very helpful for you to store values for filtering in the url
nuqs | Type-safe search params state management for Next.js
Type-safe search params state management for Next.js. Like React.useState, but stored in the URL query string.
and then in your server component you can use prisma to fetch your data while filtering out by query params in the url.
let me know if you have any questions
@James4u thank you for answer! Allow me to explain to you what the current situation is on my project, so you can perhaps explain to me 'closer' in which direction I should go.
Actually, I have specifically 4 filters, i.e. 4 categories by which I want to filter the items from the array that I display, which are (category: Dog, Cat, Others; location: some cities; ages: young, adult; gender: female and male) . What I managed to do with prisma is that when I set it up in the function on the server side like this:
export async function getAdoptPost(
context: any,
location?: string,
) {
const page = parseInt((context.query.page as string) || "1", 12);
const pageSize = 12;
const total = await db.adoptAnimal.count({});
const post = await db.adoptAnimal.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
where: {
location: location,
},
orderBy: {
createdAt: "desc",
},
});
return {
post,
page,
pageSize,
total,
};
}
this is an example where I only put 'location' as one of the possible options in the filter and now on the client side if I call this function 'getAdoptPost' and assign it 'location' something like this:
const [location, setLocation] = useState<string>("Boston");
const fetchData = (page: number) => {
startTransition(async () => {
const result = await getAdoptPost({
query: { page },
location,
});
setPosts(result.post);
setPage(result.page);
setPageSize(result.pageSize);
setLocation(location);
setTotal(result.total);
setIsLoading(false); // Set loading to false after data is fetched
console.log(result);
console.log(location);
});
};
because of this state, in which I hard-coded the location 'Boston', it will filter out all the animals that have that location on them, but I would like to make it so that the user selects that location via the filter below, and I get the results.are you doing client side data-fetching?
that I also have a FIlterMenu component on the client side where there are fields with filters and through these fields I collect the data that the user picks up from the filter. And this is a function that is called on the submit FIlterMenu and I put all those filters that the user selects in the 'allFilters' array
export const updateFilters = async (formData: FormData) => {
const categoryFilters = formData.getAll("category");
const locationFilters = formData.getAll("location");
const spolFilters = formData.getAll("spol");
const starostFilters = formData.getAll("starost");
const allFilters = [
...categoryFilters,
...locationFilters,
...spolFilters,
...starostFilters,
];
console.log("all filters", allFilters);
if (allFilters.length > 0) {
const params = new URLSearchParams([
["category", categoryFilters.join(",")],
["location", locationFilters.join(",")],
["spol", spolFilters.join(",")],
["starost", starostFilters.join(",")],
]);
console.log("params", params);
redirect(
/adoptPet?${params.toString()});
} else {
redirect("/adoptPet");
}
};
Is this looks well?sorry @tom_bombadil can you format your code?
yes I do
there is also some extra code related to
onSubmit
in the FilterMenu, ignore it for now because I'm calling the 'actions' function 'updateFilters' on onSubmit
right nowyou mean, you use server actions?
yes, that 'updateFilters' function is on the server side
should I use classic handleSubmit in the Filter Menu?
or this is fine?
server actions are for data mutation indeed - you are just redirecting right? you can do that in the client side
this is the log of that updateFilters function:
all filters [ 'Macka', 'Tuzla', 'Zensko', 'Odraslo' ]
params URLSearchParams {
'category' => 'Macka',
'location' => 'Tuzla',
'spol' => 'Zensko',
'starost' => 'Odraslo' }
middleware is running on route: /adoptPet
GET /adoptPet?category=Macka&location=Tuzla&spol=Zensko&starost=Odraslo 200 in 29ms
in 'allFilters' I place what the user has chosen as a filter and then fill in the pathname as you can see below@tom_bombadil sorry but you are not answering my questions - difficult to keep conversation in efficient way
what questions?
checked this?