0

I'm building a form—ideally using the useActionState server-action setup—that needs to persist its values during submissions. The problem is, I can't use the defaultValue prop on the element, because I need it to be a controlled component so I can update it dynamically on the client side.

My current setup

I tried making the controlled using local state, but then the server state doesn't apply correctly after submission. It resets the select value to be the first option, even though the server state and local client state both have most up to date values. Upon submitting again, it then submits that first incorrect select option ("Mini").

What can I do in this situation? Move to javascript query selectors?

I left a very simple example of my problem below.

Form:

"use client";
import { useActionState, useEffect, useState } from "react";
import { saveFormData } from "./actions";
type FormState = {
 group: string;
};
const defaultState: FormState = {
 group: "Junior",
};
export default function FormExample() {
 const [state, formAction] = useActionState(saveFormData, defaultState);
 const [group, setGroup] = useState(state.group);
 useEffect(() => {
 if (state.group !== group) {
 setGroup(state.group);
 }
 }, [state.group]);
 return (
 <form action={formAction}>
 <label>
 Group:
 <select
 name="group"
 value={group}
 onChange={(e) => setGroup(e.target.value)}
 >
 <option value="Mini">Mini (11–12)</option>
 <option value="Junior">Junior (12–14)</option>
 <option value="Senior">Senior (15+)</option>
 </select>
 </label>
 <button type="submit" className="btn">
 Submit
 </button>
 </form>
 );
}

Server action:

"use server";
export async function saveFormData(prevState: unknown, formData: FormData) {
 const group = String(formData.get("group"));
 console.log("group on server: ", group);
 
 // Persist values here (e.g., database, cookies, etc.)
 return { group };
}
asked Jul 8, 2025 at 16:19

1 Answer 1

0

This is a confirmed react 19 bug affecting the controlled <select> elements. It has introduced automatic form reset behavior that calls form.reset() after successful submissions. This creates a race condition specially with controlled <select> elements. Here is the GitHub issue

  1. Form submits -> useActionsState batches state update
  2. React's automatic reset fires -> Select DOM element reset to first option
  3. Reconsiliation runs -> But DOM was already reset, causing desynchronization.

You can use key attribute to force remount. Also since we want to force synchronization every time state.group changes, simple approach without comparison is actually better inside the useEffect

"use client";
import { useActionState, useEffect, useState } from "react";
import { saveFormData } from "./actions";
export default function FormExample() {
 const [state, formAction] = useActionState(saveFormData, { group: "Junior" });
 const [group, setGroup] = useState(state.group);
 useEffect(() => {
 setGroup(state.group); // Always sync, no comparison needed
 }, [state.group]);
 return (
 <form action={formAction}>
 <label>
 Group:
 <select
 key={`${state.group}-${Date.now()}`} // Force remount on each server update
 name="group"
 value={group}
 onChange={(e) => setGroup(e.target.value)}
 >
 <option value="Mini">Mini (11–12)</option>
 <option value="Junior">Junior (12–14)</option>
 <option value="Senior">Senior (15+)</option>
 </select>
 </label>
 <button type="submit" className="btn">
 Submit
 </button>
 </form>
 );
}
answered Jul 9, 2025 at 11:26
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.