Forms

Learn how to build forms in the Next.js Supabase kit

Now that we have created a custom hook to write data to the Database, we need to build a form to create a new task.

The example below is straightforward:

  1. We have a form with two input fields
  2. When the form is submitted, we read the data using FormData
  3. Finally, we add the document using the callback returned by the hook useCreateTask
components/tasks/CreateTaskForm.tsx
import { useNavigate } from '@remix-run/react';
import type { FormEventHandler } from 'react';
import { useCallback } from 'react';
import toaster from 'react-hot-toast';
 
import TextField from '~/core/ui/TextField';
import Button from '~/core/ui/Button';
import useCreateTaskMutation from '~/lib/tasks/hooks/use-create-task';
 
import useCurrentOrganization from '~/lib/organizations/hooks/use-current-organization';
 
const CreateTaskForm = () => {
  const createTaskMutation = useCreateTaskMutation();
  const navigate = useNavigate();
  const organization = useCurrentOrganization();
  const organizationId = organization?.id as number;
 
  const onCreateTask: FormEventHandler<HTMLFormElement> = useCallback(
    async (event) => {
      event.preventDefault();
 
      const target = event.currentTarget;
      const data = new FormData(target);
      const name = data.get('name') as string;
      const dueDate = (data.get('dueDate') as string) || getDefaultDueDate();
 
      if (name.trim().length < 3) {
        toaster.error('Task name must be at least 3 characters long');
 
        return;
      }
 
      const task = {
        organizationId,
        name,
        dueDate,
        done: false,
      };
 
      // create task
      await createTaskMutation.mutateAsync(task);
 
      // redirect to /tasks
      return navigate(`/tasks`);
    },
    [navigate, createTaskMutation, organizationId]
  );
 
  return (
    <form onSubmit={onCreateTask}>
      <div>
        <TextField.Label>
          Name
          <TextField.Input
            required
            name={'name'}
            placeholder={'ex. Launch on IndieHackers'}
          />
          <TextField.Hint>Hint: whatever you do, ship!</TextField.Hint>
        </TextField.Label>
 
        <TextField.Label>
          Due date
          <TextField.Input name={'dueDate'} type={'date'} />
        </TextField.Label>
 
        <div>
          <Button>Create Task</Button>
        </div>
      </div>
    </form>
  );
};
 
export default CreateTaskForm;
 
function getDefaultDueDate() {
  const date = new Date();
  date.setDate(date.getDate() + 1);
  date.setHours(23, 59, 59);
 
  return date.toDateString();
}

Subscribe to our Newsletter
Get the latest updates about React, Remix, Next.js, Firebase, Supabase and Tailwind CSS