I have a server action form, and I want it to be a reusable form.
// File: success_indicator/successIndicatorForm/SuccessIndicatorForm
"use client";
import SubmitBtn from "@/app/components/SubmitBtn";
import React, {useEffect, useState} from "react";
const SuccessIndicatorForm = ({state, formAction, formValues}: any) => {
const [dataForm, setFormValues] = useState({
major_final_output: "",
title: "",
target_measure: "",
});
useEffect(() => {
console.log("wwwwwwww");
setFormValues({
major_final_output: "asd",
title: "ww",
target_measure: "123",
});
}, []);
const changeHandler = (e: any) => {
setFormValues({...dataForm, [e.target.name]: e.target.value});
};
return (
<div className="max-w-max px-4 py-8 bg-white rounded-lg shadow dark:bg-gray-800 sm:px-6 md:px-8 lg:px-10 m-auto mt-20 text-white">
<form action={formAction} className="flex flex-col w-full justify-around">
<div className="relative">
<div className="flex flex-col justify-between">
<div>
<label htmlFor="major_final_output">Major Final Output:</label>
<input
value={dataForm.major_final_output} <----------!!!!! ERROR WHEN USING THIS value prop
onChange={changeHandler}
type="text"
id="major_final_output"
name="major_final_output"
placeholder="MFO 1: Human Resource Management and Development Services"
className="rounded-lg py-1 px-1 m-2 text-black"
required
/>
</div>
<SubmitBtn />
</div>
<p role="status">{state?.message}</p>
</form>
</div>
);
};
export default SuccessIndicatorForm;
but I want to use it on creating new and updating data. For now this works when creating new data. but when I tried to add a value
property on input I will get this error.
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
input
div
div
div
form
div
Also the setFormValues
won't update the form values but I can confirm it's running through log('wwwwwwww')
.
So my idea is using SuccessIndicatorForm
and passing a form value props to set the values.
I think your mixing server and client components. Your component specify "use client"
.
I think you should seperate into three components:
SuccessIndicatorFormCreate
& SuccessIndicatorFormUpdate
, the real server components containing the handlers for the create/update actionSuccessIndicatorFormContent
, the inner form agnostic for create/updateAlso, from your example, I don't see a valid reason using useState
& useEffect
.
So I think you should have something like this
// success_indicator/successIndicatorForm/SuccessIndicatorFormCreate
const SuccessIndicatorFormCreate = ({ formValues }) => {
async function formAction(formData) {
"use server";
// ...
}
return (
<form action={formAction} className="flex flex-col w-full justify-around">
<SuccessIndicatorFormContent formValues={formValues} />
</form>
);
};
// success_indicator/successIndicatorForm/SuccessIndicatorFormUpdate
const SuccessIndicatorFormUpdate = ({ formValues }) => {
async function formAction(formData) {
"use server";
// ...
}
return (
<form action={formAction} className="flex flex-col w-full justify-around">
<SuccessIndicatorFormContent formValues={formValues} />
</form>
);
};
// success_indicator/successIndicatorForm/SuccessIndicatorFormContent
const SuccessIndicatorFormContent = ({ formValues }: any) => {
return (
<div className="relative">
<div className="flex flex-col justify-between">
<div>
<label htmlFor="major_final_output">Major Final Output:</label>
<input
defaultValue={formValues.major_final_output}
type="text"
id="major_final_output"
name="major_final_output"
placeholder="MFO 1: Human Resource Management and Development Services"
className="rounded-lg py-1 px-1 m-2 text-black"
required
/>
</div>
</div>
</div>
);
};