Search functionality server -> client component confusion
Unanswered
Serbian Hound posted this in #help-forum
Serbian HoundOP
Hi, so I had a simple server-sided component that rendered a bunch of records, let's just pretend they're a list of comments. It works fine, but now I want to add filtering functionality - searching via date range, author, etc
How can I achieve this and maintain a server action performing the fetch? I was going to use
Is there any other way to achieve this? The only alternative I can think of is using the URL, but I would like to avoid this if possible (just uglifies the URL which I personally don't like)
How can I achieve this and maintain a server action performing the fetch? I was going to use
useState to keep the filter info, and pass the function upwards, but then I realised you cannot pass functions up from a client to server component.Is there any other way to achieve this? The only alternative I can think of is using the URL, but I would like to avoid this if possible (just uglifies the URL which I personally don't like)
32 Replies
@Serbian Hound Hi, so I had a simple server-sided component that rendered a bunch of records, let's just pretend they're a list of comments. It works fine, but now I want to add filtering functionality - searching via date range, author, etc
How can I achieve this and maintain a server action performing the fetch? I was going to use `useState` to keep the filter info, and pass the function upwards, but then I realised you cannot pass functions up from a client to server component.
Is there any other way to achieve this? The only alternative I can think of is using the URL, but I would like to avoid this if possible (just uglifies the URL which I personally don't like)
yes, you can. One easy way would be to have a state, that saves the search text. Then you need the server actions (or api route), that does the search for you. And then you only need a input, where the user can enter his search text. One example would be: https://gist.github.com/B33fb0n3/20f5e70c35c64c769661a9fb39f990b8
(I commented IMPORTANT to the only important things in the file)
(I commented IMPORTANT to the only important things in the file)
Serbian HoundOP
Wait..so you can have a server action in a client component? 😮
@Serbian Hound Wait..so you can have a server action in a client component? 😮
of course. Server Actions are specifically made for clientside mutations
Serbian HoundOP
I did try this, but then I get this
You're importing a component that needs next/headers. That only works in a Server Component but one of its parents is marked with "use client", so it's a Client Component.My component:
useEffect(() => {
const fetchAndSet = async () => {
const response = await fetchServerWrapper("/posts", "GET", {});
const json = await response.json();
console.log(json);
}
fetchAndSet();
}, [filters]);which then calls this:
export async function fetchServerWrapper(endpoint: string, method: string, body: Record<string, unknown>) {
const token = await getToken();
return await fetchWrapper(token ?? "", endpoint, method, body);
}
export async function getToken() {
const token = cookies().get('token')?.value
return token;
}^ and I get that's on the server
American Chinchilla
Just make sure the server component is in a speerate file
Serbian HoundOP
yeah it is 😦
American Chinchilla
It has to be marked “use server” too
On top
Serbian HoundOP
yay that fixed it!
I mean I get
PlainTable.tsx:27 Uncaught (in promise) Error: Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.but still, i think you've solved the issue 😄
American Chinchilla
You want to return as the error says an object
Serbian HoundOP
I do
export default async function fetchWrapper(token: string, endpoint: string, method: string, body: Record<string, unknown>) {
const response = await fetch("http://127.0.01:8080/" + endpoint, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
credentials: 'include',
},
body: Object.keys(body).length > 0 ? JSON.stringify(body) : undefined,
method
});
return response;
}maybe because i cant pass in a record?
but a record is a plain object
@Serbian Hound for clientside fetching you should use in every case either react query or swr. Don't fetch stuff like using useEffect or anything else...
I can show you only an example of react query, but that could be so easy with a clientside fetching library like react query or swr.
I changed the example, that I already sent like this: https://gist.github.com/B33fb0n3/79a55b5a6280905b64bb019178e15143
I changed the example, that I already sent like this: https://gist.github.com/B33fb0n3/79a55b5a6280905b64bb019178e15143
Serbian HoundOP
yeah i know using swr is better
im just trying to make it work atm
I got it working, its because I was returning the
Response object from the fetch, but cant do that, it should just be the JSON or whatever@Serbian Hound im just trying to make it work atm
so you don't want the help of bulletproof solutions, that others trust?
Serbian HoundOP
wat ?
I use SWR myself bro but im just making it work
then ill add swr
I don't wanna add more layers before i fix the problem
@Serbian Hound I don't wanna add more layers before i fix the problem
ok, now I got it. Sorry mb. Can't you just return
return response.json()? You might want to share either the code of the specific endpoint or the response@Serbian Hound ?