How do I get response data from the serverComponent back into the clientComponent?
Answered
Sloth bear posted this in #help-forum
Sloth bearOP
So I'm modifying our entire app so that all Fetch requests go through server components and not client components so that the API requests / keys etc are all hidden from the browser, and solve the CORS issue with out a Node server.
I have my page.tsx which is using Server actions to fetch form data from my Login form client component, and I'm able to Post a fetch request successfully now.
However the problems I have now in the Server Component, is that
1) I cannot store certain data in the localStorage (various tokens)
2) I cannot navigate using Link to the correct dashboard view
3) I cannot pass in a call back from the server component into the client component to handle the logic there.
What is the pattern I should use in this situation?
## Client component (The Form)
## My server (login/page.tsx) component
I have my page.tsx which is using Server actions to fetch form data from my Login form client component, and I'm able to Post a fetch request successfully now.
However the problems I have now in the Server Component, is that
1) I cannot store certain data in the localStorage (various tokens)
2) I cannot navigate using Link to the correct dashboard view
3) I cannot pass in a call back from the server component into the client component to handle the logic there.
What is the pattern I should use in this situation?
## Client component (The Form)
'use client';
const LoginForm = ({ action }: any) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(e.currentTarget);
await action(formData); // Invoke the action function with formData
console.log('Form submitted');
// console.log(formData);
};
return (
<>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
id="email"
placeholder="Email Address"
required
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
name="password"
id="password"
placeholder="Password"
required
/>
</div>
<div className="actions">
<button type="submit">Submit</button>
</div>
</form>
</>
);
};
export default LoginForm;## My server (login/page.tsx) component
import LoginForm from '@/components/auth/login-form';
import { isValidEmail } from '@/utils/validators';
import {
API_KEY,
API_KEY_NAME,
API_LOGIN,
} from '@/constants';
if (!API_LOGIN) {
throw new Error('API URL is not defined');
}
const LoginPage = () => {
async function myFormProcessor(formData: any) {
'use server';
const email = formData.get('email');
const password = formData.get('password');
if (!isValidEmail(email)) {
throw new Error('Error: 400 - Invalid email address');
}
console.log('API_KEY', API_KEY);
const payload = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
[API_KEY_NAME]: API_KEY,
},
body: JSON.stringify({ user: email, password }),
};
console.log('payload', payload);
try {
const response = await fetch(API_LOGIN, payload);
console.log('Auth response:', response);
if (!response.ok) {
throw new Error('Failed to fetch');
}
const data = await response.json();
console.log('TIME TO REDIRECT TO /POSTINGS');
// router.push('/postings');
} catch (error) {
console.error(error);
}
}
return (
<div id="auth-container">
<Link href="/">
<h1 className="logo">
Bounty<strong>Jobs</strong>
</h1>
</Link>
<LoginForm action={myFormProcessor} />
</div>
);
};
export default LoginPage;Answered by Ray
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(e.currentTarget);
const data = await action(formData); // get response data from server action
// console.log(formData);
if (data) {
console.log('Form submitted');
localStorage.setItem('data', JSON.stringity(data)) // store the data to localStorage
router.push("/") // handle navigation
}
};9 Replies
Brown bear
https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations
Try using form action instead of onSubmit, and use server actions as the action.
Try using form action instead of onSubmit, and use server actions as the action.
@Sloth bear So I'm modifying our entire app so that all Fetch requests go through **server components** and not **client components** so that the API requests / keys etc are all hidden from the browser, and solve the CORS issue with out a Node server.
I have my page.tsx which is using Server actions to fetch form data from my Login form client component, and I'm able to Post a fetch request successfully now.
However the problems I have now in the Server Component, is that
1) I cannot store certain data in the localStorage (various tokens)
2) I cannot navigate using Link to the correct dashboard view
3) I cannot pass in a call back from the server component into the client component to handle the logic there.
What is the pattern I should use in this situation?
## Client component (The Form)
'use client';
const LoginForm = ({ action }: any) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(e.currentTarget);
await action(formData); // Invoke the action function with formData
console.log('Form submitted');
// console.log(formData);
};
return (
<>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
id="email"
placeholder="Email Address"
required
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
name="password"
id="password"
placeholder="Password"
required
/>
</div>
<div className="actions">
<button type="submit">Submit</button>
</div>
</form>
</>
);
};
export default LoginForm;
## My server (login/page.tsx) component
import LoginForm from '@/components/auth/login-form';
import { isValidEmail } from '@/utils/validators';
import {
API_KEY,
API_KEY_NAME,
API_LOGIN,
} from '@/constants';
if (!API_LOGIN) {
throw new Error('API URL is not defined');
}
const LoginPage = () => {
async function myFormProcessor(formData: any) {
'use server';
const email = formData.get('email');
const password = formData.get('password');
if (!isValidEmail(email)) {
throw new Error('Error: 400 - Invalid email address');
}
console.log('API_KEY', API_KEY);
const payload = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
[API_KEY_NAME]: API_KEY,
},
body: JSON.stringify({ user: email, password }),
};
console.log('payload', payload);
try {
const response = await fetch(API_LOGIN, payload);
console.log('Auth response:', response);
if (!response.ok) {
throw new Error('Failed to fetch');
}
const data = await response.json();
console.log('TIME TO REDIRECT TO /POSTINGS');
// router.push('/postings');
} catch (error) {
console.error(error);
}
}
return (
<div id="auth-container">
<Link href="/">
<h1 className="logo">
Bounty<strong>Jobs</strong>
</h1>
</Link>
<LoginForm action={myFormProcessor} />
</div>
);
};
export default LoginPage;
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // Prevent default form submission
const formData = new FormData(e.currentTarget);
const data = await action(formData); // get response data from server action
// console.log(formData);
if (data) {
console.log('Form submitted');
localStorage.setItem('data', JSON.stringity(data)) // store the data to localStorage
router.push("/") // handle navigation
}
};Answer
Sloth bearOP
Thank you! Will try today 😄
Sloth bearOP
It doesn't like this
<form action={handleSubmit}>
{/* <form onSubmit={handleSubmit}> */}And when I kept this, and had another successful login:
This did not log out
<form onSubmit={handleSubmit}>This did not log out
const data = await action(formData); // get
if (data) {
console.log('Form submitted');
console.log('data', data);
}@Sloth bear And when I kept this, and had another successful login:
`<form onSubmit={handleSubmit}>`
This did not log out
const data = await action(formData); // get
if (data) {
console.log('Form submitted');
console.log('data', data);
}
did you return the data from server action?
try {
const response = await fetch(API_LOGIN, payload);
console.log('Auth response:', response);
if (!response.ok) {
throw new Error('Failed to fetch');
}
const data = await response.json();
console.log('TIME TO REDIRECT TO /POSTINGS');
return data
// router.push('/postings');
} catch (error) {
console.error(error);
}Sloth bearOP
ah did forget that
Yes I get it back in the client now! 😄