我用的是Nextjs14和Supplement。
我有这个select
,用户可以从中选择。我还将它传递给formValue
,它将在服务器操作上作为FormData
接收。现在,在组件上,我可以看到formValue
的数据和barangay
字段。然而,在服务器操作上传递,该barangay
字段不再可以在服务器上看到的动作.
这是我的可重用组件,名为DropDownList.tsx
:
import React, { Fragment, useState, useEffect } from 'react';
import { Listbox, Transition } from '@headlessui/react';
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid';
type Props = {
options: string[];
selected: string;
onSelect: (value: string) => void;
required: boolean;
placeholder: string;
value: string;
name: string;
};
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(' ');
}
const DropdownList: React.FC<Props> = ({ options, selected, onSelect, required, placeholder , value, name}) => {
// Initialize the selected state with the default selected value from the parent
const [currentSelected, setCurrentSelected] = useState<string | null>(selected);
// Update the selected state when the selected prop changes
useEffect(() => {
setCurrentSelected(selected);
}, [selected]);
return (
<Listbox value={currentSelected} onChange={(value) => {
if (value !== null) {
setCurrentSelected(value);
onSelect(value);
}
}}>
{({ open }) => (
<>
<Listbox.Label className="block text-sm font-medium leading-6 text-gray-900">
Select an option
</Listbox.Label>
<div className="relative mt-2">
<Listbox.Button className={`relative w-full cursor-default rounded-md bg-white py-1.5 pl-3 pr-10 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus-ring-indigo-500 sm:text-sm sm:leading-6 ${required ? 'required' : ''}`}>
<span className="ml-3 block truncate">{currentSelected || placeholder}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2">
<ChevronUpDownIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</span>
</Listbox.Button>
<Transition
show={open}
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{/* Add a placeholder option */}
<Listbox.Option key="placeholder" value="" disabled>
{({ active }) => (
<span className={classNames('text-gray-500', 'ml-3 block truncate')}>
{placeholder}
</span>
)}
</Listbox.Option>
{options.map((option, i) => (
<Listbox.Option
key={i}
className={({ active }) =>
classNames(
active ? 'bg-indigo-600 text-white' : 'text-gray-900',
'relative cursor-default select-none py-2 pl-3 pr-9'
)
}
value={option}
>
{({ selected, active }) => (
<>
<span className={classNames(selected ? 'font-semibold' : 'font-normal', 'ml-3 block truncate')}>
{option}
</span>
{selected ? (
<span
className={classNames(
active ? 'text-white' : 'text-indigo-600',
'absolute inset-y-0 right-0 flex items-center pr-4'
)}
>
<CheckIcon className="h-5 w-5" aria-hidden="true" />
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
);
};
export default DropdownList;
字符串
**我在这个表单上使用它:**在这个部分,我可以看到值barangay
。
'use client'
import addWaterStation from "@/app/auth/actions/WaterStation/addWaterStation";
import React, { useEffect, useState} from "react";
import { useFormState, useFormStatus } from "react-dom";
import DropdownList from "@/components/Reusables/MyDropDownList";
import { barangay } from "./barangay";
interface FormData {
...rest of the values
barangay: string;
}
const initialState = {
message: null,
}
function SubmitButton() {
const { pending } = useFormStatus()
return (
<button type="submit" aria-disabled={pending}>
Submit
</button>
)
}
export default function WaterStationProfileForm() {
const [state, formAction] = useFormState(addWaterStation, initialState)
const [selectedBarangay, setSelectedBarangay] = useState<string>(''); // Rename the state variable
const handleBarangaySelection = (value: string) => {
setSelectedBarangay(value); //get the selected barangay
}
const [formValue, setFormValue] = useState<FormData>({
...rest of the values
barangay: "",
});
useEffect(() => {
setFormValue(prevFormValue => ({
...prevFormValue,
barangay: selectedBarangay
}))
},[selectedBarangay])
console.log(formValue, "form value") // I can see the value of barangay here
return (
<div className="container mx-auto p-4">
<form action={formAction}>
...the rest of the inputs
<DropdownList
options={barangay}
value={formValue.barangay}
selected={selectedBarangay}
onSelect={handleBarangaySelection}
required={true}
placeholder="Please select an option"
name="barangay"
/>
<SubmitButton />
</form>
</div>
);
}
型
**我的服务器操作:**在此部分,值barangay
不再存在。只有其余的值显示。示例FormData
值。barangay
不在name
上并且没有值:
FormData {
[Symbol(state)]: [
{ name: '$ACTION_REF_1', value: '' },
{
name: '$ACTION_1:0',
value: '{"id":"32933f3a25fdc884c208dbcbf3540cf9ccf38c62","bound":"$@1"}'
},
{ name: '$ACTION_1:1', value: '[{"message":null}]' },
{ name: '$ACTION_KEY', value: 'k3775125042' },
{ name: 'zone', value: '7' },
{ name: 'delivery_mode', value: 'Delivery and Pickup' },
{ name: 'contact_no', value: '9676832484' },
{ name: 'tel_no', value: '' },
{ name: 'remarks', value: '' }
]
} formData
型
服务端动作编码:
'use server'
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs"
import { revalidatePath } from "next/cache";
import { cookies } from "next/headers"
export default async function addWaterStation(prevState: any, formData: FormData): Promise<{ message: string }> { const supabase =createServerComponentClient({cookies})
const {data: {user}} = await supabase.auth.getUser();
const formDataAddress = `${formData.get('buildingNumber')}, ${formData.get('street')}, ${formData.get('zone')}`
console.log(formData, "formData")
try{
const station_name = formData.get('name')
const {data, error} = await supabase.from('water_refilling_station')
.insert({
...rest of the inputs here
barangay,
}).select()
if(error){
return {message: `${error.message} - unable to save`}
}
revalidatePath('/water_station')
return { message: `Succesfully added the data` }
}catch(e){
return {message: "Failed to submit the form."}
}
}
型
1条答案
按热度按时间k97glaaz1#
在
<form>
中放置一个隐藏的输入,只有输入值被传递给表单操作。你可以用两种方法来解决这个问题,要么在你的下拉列表旁边呈现这个:
字符串
或者在你的下拉列表中呈现:
型