After login, how to get stored cookie/localStorage data into server component?
Answered
Sloth bear posted this in #help-forum
Sloth bearOP
Thanks @Ray for helping me out in my last question about Login with server component.
Now I am able to store the tokens I need, idToken, personId into cookies or localStorage from the login-form client component. Next I redirect to /postings, which loads up my postings/page server component.
And that page component needs to get a fetch from another server component fetchPostings.
I'm able to set the cookies and localStorage, but unable to fetch the required tokens from page and send them into fetchPostings to make the next call.
I read that js-cookies would let me solve that, but the tokens are undefined, I tried cookies from next/headers, but got an error saying I can't do that.
Is there another way to pass those tokens after login into server components for another call?
The only other thing I can think of is while I'm in the login server component, to go ahead and make that getUserPostings call there, then passing everything into the login-form client component to pass on.
## My postings/page (server component)
## My fetchPostings (server component)
## my login-form (client component)
Where I save the cookies/localStorage
Now I am able to store the tokens I need, idToken, personId into cookies or localStorage from the login-form client component. Next I redirect to /postings, which loads up my postings/page server component.
And that page component needs to get a fetch from another server component fetchPostings.
I'm able to set the cookies and localStorage, but unable to fetch the required tokens from page and send them into fetchPostings to make the next call.
I read that js-cookies would let me solve that, but the tokens are undefined, I tried cookies from next/headers, but got an error saying I can't do that.
Is there another way to pass those tokens after login into server components for another call?
The only other thing I can think of is while I'm in the login server component, to go ahead and make that getUserPostings call there, then passing everything into the login-form client component to pass on.
## My postings/page (server component)
import Cookies from 'js-cookie';
// import { cookies } from 'next/headers';
import PostingsList from '@/components/postings/postings-list';
import fetchPostings from '@/services/postings';
export default async function Postings() {
let postingsData = [];
let errorMessage;
const cookies = new Cookies();
// const cookieStore = cookies();
const idToken = cookies.get('idToken') ?? '';
const personId = cookies.get('personId') ?? '';
// console.log('idToken', idToken);
// console.log('personId', personId);
try {
postingsData = await fetchPostings(idToken, personId);
console.log('postingsData', postingsData);
} catch (error: any) {
errorMessage = error.message;
}
return (
<>
<PostingsList postings={postingsData} errorMessage={errorMessage} />
</>
);
};## My fetchPostings (server component)
'user server';
import { API_GET_POSTINGS, METHOD_GET } from '@/constants';
const fetchPostings = async (idToken: string, personId: string) => {
const generateSearchParams = () => {
const params = new URLSearchParams();
params.append('posting-state', 'all');
params.append('page', '1');
params.append('page-size', '5');
return params;
};
const params = generateSearchParams();
try {
const response = await fetch(API_GET_POSTINGS(personId || '', params), {
...METHOD_GET,
headers: {
Authorization: idToken || '',
},
});
if (!response.ok) {
throw new Error(`Error fetching postings: ${response.statusText}`);
}
const data = await response.json();
console.log('fetching postings data:', data);
return data;
} catch (error: any) {
console.error(error);
return error;
}
};
export default fetchPostings;## my login-form (client component)
Where I save the cookies/localStorage
// ? store idToken in redux
if (idToken) {
cookies().set('idToken', idToken);
localStorage.setItem('idToken', idToken);
}Answered by Ray
try this
import { cookies } from 'next/headers';
const cookieStore = cookies();
const idToken = cookieStore.get('idToken')?.value ?? '';
const personId = cookieStore.get('personId')?.value ?? '';42 Replies
Sloth bearOP
Ok yes I did get that to work now thanks 🙂
const personId = allCookies.find(cookie => cookie.name === 'personId');
const idToken = allCookies.find(cookie => cookie.name === 'idToken');I'm running into this error tho
But need to fix something and try again
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 need to fix something and try again
I think you need
const personId = allCookies.find(cookie => cookie.name === 'personId') ?? '';
const idToken = allCookies.find(cookie => cookie.name === 'idToken') ?? '';Sloth bearOP
Yes thats what I have, but now I keep running into this
I'm using cookies from next/headers in my login client component, going to try use js-cookies there again.
Just strange I have to use 2 different cookie libs
Error:
× You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/
│ react-essentials#server-componentsI'm using cookies from next/headers in my login client component, going to try use js-cookies there again.
Just strange I have to use 2 different cookie libs
@Sloth bear Yes thats what I have, but now I keep running into this
Error:
× You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/
│ react-essentials#server-components
I'm using cookies from next/headers in my login client component, going to try use js-cookies there again.
Just strange I have to use 2 different cookie libs
I think you have stored the token to localStorage too?
Sloth bearOP
yes I do, but I can't get to localStorage from my server component, or at least, I don't know how
if so, just read from there in the client component, so you don't need to use
cookies()Sloth bearOP
But I have to make all my calls from server components now
The reason is
1) we hide the API key
2) avoid CORs issues
2) avoid CORs issues
So I login, I save the cookies and localStorage
@Sloth bear Yes thats what I have, but now I keep running into this
Error:
× You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/
│ react-essentials#server-components
I'm using cookies from next/headers in my login client component, going to try use js-cookies there again.
Just strange I have to use 2 different cookie libs
then why are you trying to read cookies in client component lol
Sloth bearOP
Next I route to /postings, and I need to GET postings, but with those vars I saved
Oh no ignore the login component, I'm using cookie logic there to SAVE the cookies
sec going to try again
Willing to screenshare? 😄 I can pay for some time via CashApp or Bitcoin
liveshare?
Sloth bearOP
yeah
discord call or google meet
vscode extension lol
Sloth bearOP
oh
ok I have it installed how do I use it?
ah crap I'm hiding the status bar 1 sec
can you see my other tabs? or just this one?
try again
fetching
Sloth bearOP
same error
Uncaught 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.
Sloth bearOP
forbidden I'll login again real quick
oh wait, no more error now
the Postings call is forbidden but app doesn't break hmm
⨯ 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.
at stringify (<anonymous>)
queryString: ?posting-state=all&page=1&page-size=5
response.status 403
Error: Error fetching postings: Forbiddenok I still see Forbidden, so it may be our Backend issue
but ok so that Only Plain Objects error, I don't get that message in the browser anymore, only in the terminal, which is better?
Thanks! Getting closer
Sloth bearOP
gotcha, throw it instead
Appreciate it
Sloth bearOP
This is solved now, again thanks! 😄