NextJS 13 APP routing - anti pattern - weird behavior
Unanswered
Siberian posted this in #help-forum
SiberianOP
I'm wondering if I am doing some leakage/incorrect practices in NextJS.
The functionality that I want to happen is
Comment is added via form -> Action is triggered on server -> new comment is added into db -> page is refreshed
It works, but if I change the code in page.tsx and add a single line at the top:
'use server';
I get an error saying you cant pass event listeners to functions... Which is really strange, I heard that all the components inside of the app directory are server by default.
Also, if I don't declare videos outside of the component:
And instead declare the variable here
I'm getting strange errors upon hitting the submit button. What is going on?
app/page.tsx
app/components/AddComment.tsx
The functionality that I want to happen is
Comment is added via form -> Action is triggered on server -> new comment is added into db -> page is refreshed
It works, but if I change the code in page.tsx and add a single line at the top:
'use server';
I get an error saying you cant pass event listeners to functions... Which is really strange, I heard that all the components inside of the app directory are server by default.
Also, if I don't declare videos outside of the component:
let video: Video | null = null;
And instead declare the variable here
(let) video = await videosDao.getVideoWithCommentsById(params.id);
I'm getting strange errors upon hitting the submit button. What is going on?
app/page.tsx
let video: Video | null = null;
const VideoPage: NextPage<Props> = async ({ params }) => {
// Assume you have fetched video, comments, and related videos
// pass them to their respective components as props
video = await videosDao.getVideoWithCommentsById(params.id);
const addComment = async (data: FormData) => {
'use server';
try{
let inserted = await commentsDao.insertComment(comment);
video?.comments?.push(comment as Comment);
revalidatePath(`/video/${videoId}/${video?.name}`);
}
const relatedVideos = await videosDao.getRelatedVideos(video);
return (
<div className="grid lg:grid-cols-4 gap-4 mt-2 md:grid-cols-1">
<AddComment onAddComment={addComment}/>
</div>
)
}
export default VideoPage;
app/components/AddComment.tsx
'use client';
const AddComment: React.FC<AddCommentProps> = ({ onAddComment }) => {
return (
<div className="flex flex-row space-x-4 lg:w-11/12 md:w-full p-4 shadow rounded bg-gray-800">
<form action={onAddComment} className="flex flex-row space-x-4 flex-grow">
<div className="flex-1">......
5 Replies
SiberianOP
A side question:
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault(); // This prevents the default form submission behavior
startTransition( async () => {
// Create FormData instance
const data = new FormData(event.currentTarget);
// Call the server action
let res = await onAddComment(data);
// Display the error message if it exists
if(res.error) {
setError(res.error.charAt(0).toUpperCase() + res.error.slice(1));
} else {
setError('');
}
// If the comment was successfully added, reset the input fields
if(res.success) {
setComment('');
setNickname('');
}
});
};
If I change the code in AddComment in this way, where I'm taking a server function and calling it onSubmit, is this an antipattern and is my parent component (page.tsx) still a server page?
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault(); // This prevents the default form submission behavior
startTransition( async () => {
// Create FormData instance
const data = new FormData(event.currentTarget);
// Call the server action
let res = await onAddComment(data);
// Display the error message if it exists
if(res.error) {
setError(res.error.charAt(0).toUpperCase() + res.error.slice(1));
} else {
setError('');
}
// If the comment was successfully added, reset the input fields
if(res.success) {
setComment('');
setNickname('');
}
});
};
If I change the code in AddComment in this way, where I'm taking a server function and calling it onSubmit, is this an antipattern and is my parent component (page.tsx) still a server page?
Alfonsus Ardani
"use server" does not mean mark a component into server component and does not have anything to do with react components at all
SiberianOP
Thanks, so I just confused that with the 'use client' directive, which does mark the component as client sided and allows for the usage of useState etc?
Alfonsus Ardani
yep
Julienng
This is not an antipattern :), and it is documented here by Next.js: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions#custom-invocation-using-starttransition