- Documentation
- /
- Next.js Firebase
- /
- Writing data to Firestore
Writing data to Firestore
Learn how to write, update and delete data using Firestore in Makerkit
Similarly to reading data from Firestore, we may want to create a `custom hook`` also when we write, update or delete data.
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
collection name tolib/firestore-collections
- Wrap the
addDoc
function from Firestore within auseCallback
hook
import { TASKS_COLLECTION } from '~/lib/firestore-collections';
function useCreateTask() {
const firestore = useFirestore();
const tasksCollection = collection(firestore, TASKS_COLLECTION);
return useCallback(
(task: Task) => {
return addDoc(tasksCollection, task);
},
[tasksCollection]
);
}
And now, we could use this hook within a component:
function Component() {
const createTask = useCreateTask();
return <MyForm onSubmit={task => createTask(task)} />
}
Let's take a look at a complete example of a form that makes a request using the hook above:
const CreateTaskForm = () => {
const createTask = useCreateTask();
const { setLoading, state } = useRequestState();
const router = useRouter();
const organization = useCurrentOrganization();
const organizationId = organization?.id as string;
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;
setLoading(true);
const task = {
organizationId,
name,
dueDate,
description: ``,
done: false,
};
await toaster.promise(createTask(task), {
success: `Task created!`,
error: `Ops, error!`,
loading: `Creating task...`,
});
await router.push(`/tasks`);
},
[router, createTask, organizationId, setLoading]
);
return (
<div>
<form onSubmit={onCreateTask}>
<div className={'flex flex-col space-y-3'}>
<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
required
defaultValue={getDefaultDueDate()}
name={'dueDate'}
type={'date'}
/>
</TextField.Label>
<div
className={
'flex flex-col space-y-2 md:space-y-0 md:space-x-2' +
' md:flex-row'
}
>
<Button loading={state.loading}>
<If condition={state.loading} fallback={<>Create Task</>}>
Creating Task...
</If>
</Button>
<Button color={'transparent'} href={'/tasks'}>
Go back
</Button>
</div>
</div>
</form>
</div>
);
};
function getDefaultDueDate() {
const date = new Date();
const year = date.getFullYear();
const month = pad(date.getMonth() + 1);
const day = pad(date.getDate() + 1);
return `${year}-${month}-${day}`;
}
function pad(n: number) {
return n < 10 ? `0${n}` : n.toString();
}
export default CreateTaskForm;