With the exciting features of RSC and server action released by React 19, we are going to use them to build a high-performance form. Here is our trying:
We build a very small client-component form.
'use client'import { Fieldset, Form } from '@heroui/react' import { useActionState } from 'react'
export function MyForm({ action, children }) { const [state, submitAction, isPending] = useActionState(action, { error: null, })
return ( <Form onSubmit={submitAction} validationErrors={state?.error}> <Fieldset disabled={isPending} className='h-full flex flex-col gap-0'> {children} </Fieldset> </Form> ) }
Then we can make other parts RSC.
import { TextField, Label, Input, FieldError, Button } from '@heroui/react' import { MyForm } from './myForm' import { uploadDataset } from './actions'export function MyDataset() { return ( <MyForm action={uploadDataset}> <TextField name='title'> <Label>title</Label> <Input /> <FieldError /> </TextField> <TextField name='description'> <Label>description</Label> <Input /> <FieldError /> </TextField> <Button type='submit'>upload</Button> </MyForm> ) }
Here are some points:
We make most of the form RSC. So it is fast and the js size is small.
Thanks the components of
<Form>, <TextField>, <FieldError>from HeroUI, it is easy to propagate error messages.Server action and uncontrolled components make the code concise and clean. No states and no coherent between components.
But, there is only one thing:
The input texts are cleaned even if uploadDataset returns error.
How to prevent text from resetting?
There are several solutions/workarounds we investigated:
- Use
onSubmit. We are using it. But we really want to switch to server action. - Let
useActionStatereturns previous states and fill them intodefaultValue. Then we have to move all the controls into<MyForm>. It adds coherence and loses RSC. - Controlled text field. It adds coherence and loses RSC.
Any good idea?