Next.js Discord

Discord Forum

Next.js and Supabase: Over 5 Seconds Waiting for Server Response in Server Action

Unanswered
Shih Tzu posted this in #help-forum
Open in Discord
Shih TzuOP
I am trying to have a server action in Next.js which is called from a component. This server action is supposed to insert 25 records into a database. This process is taking over 5 seconds. Is this longer than expected? Are there any ways to speed it up?

33 Replies

Shih TzuOP
<form action={updateQuiz}>
  <!-- input fields -->
</form>
I am currently in the process of pasting the code.
export async function updateQuiz(formData) {
    const cookieStore = cookies();const supabase = createServerComponentClient({cookies : () => cookieStore});const {data: {session}} = await supabase.auth.getSession();const user = session?.user;
    if (!user) {console.error("User is not authenticated - updateQuiz server action");return;}const id = formData.get('id');const name = formData.get('name');const category = formData.get('category');const description = formData.get('description');const { data: quizData, error: quizError } = await supabase.from('quiz').update({name, category, description}).match({id, user_id: user.id}).select();if (quizError) {return} if (quizData.length !== 1) {return} const quiz = quizData[0];
const { error: questionsError } = await supabase.from('question').delete().eq('quiz_id', quiz.id);
let questionNumber = 1; while (true) {if (formData.get(`q${questionNumber}`) === null){break} else 
{let questionText = formData.get(`q${questionNumber}`);let choice1 = formData.get(`q${questionNumber}c1`);let choice2 = formData.get(`q${questionNumber}c2`);let choice3 = formData.get(`q${questionNumber}c3`);let choice4 = formData.get(`q${questionNumber}c4`);const { data: questionData, error: questionError } = await supabase.from('question').insert([{ 'question_text': questionText, 'quiz_id': quiz.id, 'question_number': questionNumber }]).select(); const question = questionData[0]; const { data: choice1Data, error: choice1Error } = await supabase.from('choice').insert({ 'question_id': question.id, 'choice_text': choice1, 'is_correct': true }).select(); const { data: choice2Data, error: choice2Error } = await supabase.from('choice').insert({ 'question_id': question.id, 'choice_text': choice2, 'is_correct': false }).select()
const { data: choice3Data, error: choice3Error } = await supabase.from('choice').insert({ 'question_id': question.id, 'choice_text': choice3, 'is_correct': false }).select()
const { data: choice4Data, error: choice4Error } = await supabase.from('choice').insert({ 'question_id': question.id, 'choice_text': choice4, 'is_correct': false }).select()
        }questionNumber++}if (formData.get('next') === 'close') {revalidatePath(`/quizzes`); redirect('/quizzes')
    } else if (formData.get('next') === 'continue') {revalidatePath(`/quiz/${id}`)}}
I am not receiving any errors in the console. I could see how long it was taking in the network tab of dev tools.
To try to solve the issue, I have tried to re-run the code at a different time of day to see if it was a problem of supabase's end.
Shih TzuOP
Increasing the number of questions to around 10 times out the request since it gets above 10 seconds which is too high for Vercel.
Toyger
I think the problem that you run a lot of queries sequentially, and because of that additional network time added to that.
also queries is heavy.
you should to rewrite your data to bulk insert like
const { error } = await supabase
  .from('countries')
  .insert([
    { id: 1, name: 'Nepal' },
    { id: 1, name: 'Vietnam' },
  ])


and you should not return inserted data that you return with .select()
it add additional load to server.
you have all data in your script, you don't need to return it, you need only check if error happened on insert, and with bulk insert it will be only 1 query.
Shih TzuOP
Ok, I will try this and see if the speed improves.
Toyger
also maybe your supabase instance located too far from nextjs instance and it add time for network query additionally
Shih TzuOP
Also, I have noticed that using server actions with Next.js has produced slower results compared to React + some sort of requests to backend.
 const addTask = async (newTask) => {
    if (newTask.title !== "") {
      if (user) {
        const tasksCollectionRef = collection(db, "tasks");
        try {
          const newTaskWithUser = { ...newTask, userId: user.uid};
          const docRef = await addDoc(tasksCollectionRef, newTaskWithUser);
          const taskId = docRef.id;
          const taskWithId = { ...newTask, id: taskId};
          const newTasks = [taskWithId, ...tasks];
          setTasks(newTasks);
        } catch (error) {}
      } else {
        const newTasks = [newTask, ...tasks];
        setTasks(newTasks);
        window.localStorage.setItem('tasks', JSON.stringify(newTasks));
      }
    }
  }
For example, the above is some jsx code from a different project. It was a React and Firebase to-do list app.
Here, the update was almost instantaneous on the page,
Toyger
Also, I have noticed that using server actions with Next.js has produced slower results compared to React + some sort of requests to backend using fetch
iirc they are only some abstractions over it, so at the end they are same, it should be like microseconds difference that insignificant
so it's impossible to compare
Shih TzuOP
In my form, I have two buttons. Each of them add a name and value to the form data. This enables me to perform a slightly different operation in the server action depending on which button is pressed. However, pressing the enter symbol after the input automatically assumes that I want to perform the action based on the name and value in the first button. Why is this the case? How can I disable submitting the form with the enter key?
Shih TzuOP
<form action={serverAction}>
    <button type="submit" name="next" value="close">Save and Close</button>
    <button type="submit" name="next" value="continue">Save and Continue Editing</button>
</form>
The enter key performs the same operation that the Save and Close button would. Why?
Why not the other button?

Separate question: is there a way to disable the enter key having any effect on form submission?
Toyger
it browser default behaviour it get first "submit" element and perform it.
theoretically you can disable it by adding to form this:
onKeyPress={(e) => { e.key === 'Enter' && e.preventDefault(); }}
Shih TzuOP
onKeyPress is deprecated
I have also noticed that the request is faster to process on localhost compared to in production. This could be because of the location of the serverless function on Vercel.
Shih TzuOP
I do have another help forum post open. It has been a day so it's unlikely that anyone sees it, but the problem has still not been resolved. It is about props, server components, client components, useState and useEffect.
@Shih Tzu onKeyPress is deprecated
Toyger
try onKeyDown
@Toyger try `onKeyDown`
Shih TzuOP
yes this works
@Toyger of course on localhost you have almost 0 ping, but on vercel it's at least milliseconds
Shih TzuOP
Vercel is 3 times slower though (3 seconds vs 9 seconds)
i'll do bulk inserts and see if that fixes the problem
Shih TzuOP
ok, do you want to go to that one now?
Toyger
ok