- Documentation
- /
- Remix Supabase
- /
- Writing data to Database
Writing data to Database
Learn how to write, update and delete data using the Supabase Database in Makerkit
Similarly to reading data, we may want to create a custom hook
also when we write, update or delete data to our Supabase database.
Assuming we have an entity called tasks
, and we want to create a hook to
create a new Task
, we can do the following.
- First, we create a new hook at
lib/tasks/hooks/use-create-task.ts
- We add the
tasks
table name tolib/db-tables.ts
- We create a
mutations.ts
file withinlib/tasks
export const TASKS_TABLE = `tasks`;
In our mutations file, we will add all the mutations we want to perform on
the tasks
table. In this case, we will add a createTask
mutation.
export function createTask(
client: Client,
task: Task,
) {
return client.from(TASKS_TABLE).insert(task).throwOnError();
}
Now, we can use the createTask
mutation in our useCreateTask
hook.
We will be using the useMutation
hook from react-query
to create our hook.
function useCreateTaskMutation(task: Task) {
const client = useSupabase();
return useMutation(
async (task: Task) => {
return createTask(client, task);
}
);
}
export default useCreateTaskMutation;
Let's take a look at a complete example of a form that makes a request using the hook above:
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();
}