# 4.3 Updating Tasks

Our users may want to edit their tasks or mark them as complete. We will have to create a form very similar to the one in [Chapter 4.1](/core/tutorial/4.-crud-operations/4.1-creating-tasks.md). The only difference is that we need to query task data and prefill the form with it.

### Step 1: Create Mutation

Let's start by creating an update mutation. This will be used when a user submits the form.

{% code title="src/components/EditTaskForm/UpdateTaskMutation.graphql.ts" %}

```typescript
import gql from 'graphql-tag';

export const UpdateTaskMutation = gql`
	mutation UpdateTaskMutation(
		$id: UUID!
		$title: String
		$description: String
		$completed: Boolean
	) {
		updatetasksCollection(
			filter: { id: { eq: $id } }
			set: {
				title: $title,
				description: $description,
				completed: $completed
			}
		) {
			affectedCount
			records {
				id
				title
				description
				completed
			}
		}
	}
`;

```

{% endcode %}

### Step 2: Generate Typings

We will now generate typescript interfaces for our GraphQL API. Execute the following command:

```
yarn graphql-codegen
```

This will update the file `src/graphql-types.ts`.

### Step 3: Create Form

Create the following component:

{% code title="src/components/EditTaskForm/EditTaskForm.tsx" %}

```typescript
import { getComponent, useNavigation } from '@bluebase/core';
import { JsonGraphqlFormProps } from '@bluebase/plugin-json-graphql-components';
import React, { useCallback } from 'react';

import {
	TasksCollectionQueryQuery,
	TasksCollectionQueryQueryVariables,
	TasksInsertInput,
	UpdateTaskMutationMutationVariables
} from '../../graphql-types';
import { TasksCollectionQuery } from '../TaskList/TasksCollectionQuery.graphql';
import { UpdateTaskMutation } from './UpdateTaskMutation.graphql';

const JsonGraphqlForm = getComponent<JsonGraphqlFormProps<any>>('JsonGraphqlForm');

export interface EditTaskFormProps {
	id: string;
}

export const EditTaskForm = (props: EditTaskFormProps) => {
	const { navigate } = useNavigation();
	const { id } = props;

	const onSuccess = useCallback(() => {
		navigate('TasksApp');
	}, []);

	const mapQueryDataToInitialValues = useCallback(
		(data: TasksCollectionQueryQuery) => {
			return data?.tasksCollection?.edges[0]?.node;
		}, []);

	const mapFormValuesToMutationVariables = useCallback(
		(task: TasksInsertInput): UpdateTaskMutationMutationVariables => {
			return {
				id: task.id,
				title: task.title,
				description: task.description,
				completed: task.completed
			};
		}, []);

	const queryVariables: TasksCollectionQueryQueryVariables = {
		filter: {
			id: { 'eq': id }
		}
	};

	return (
		<JsonGraphqlForm
			query={{
				query: TasksCollectionQuery,
				variables: queryVariables
			}}
			mutation={{
				mutation: UpdateTaskMutation,
				refetchQueries: [TasksCollectionQuery],
				awaitRefetchQueries: true
			}}
			onSuccess={onSuccess}
			mapFormValuesToMutationVariables={mapFormValuesToMutationVariables}
			mapQueryDataToInitialValues={mapQueryDataToInitialValues}
			{...props}
			schema={{
				validateOnBlur: false,
				validateOnChange: false,

				fields: [
					{
						autoFocus: true,
						label: 'Title',
						name: 'title',
						required: true,
						type: 'text',
					},
					{
						label: 'Description',
						name: 'description',
						type: 'text',
					},
					{
						label: 'Completed',
						name: 'completed',
						type: 'checkbox',
					},
					{
						name: 'status',
						type: 'status',
					},
					{
						name: 'submit',
						title: 'Update Task',
						type: 'submit',
					},
				],
			}}
		/>
	);
};

EditTaskForm.displayName = 'EditTaskForm';
```

{% endcode %}

Explanation:

* **Line 22**: We take task ID as a prop. This will be used as a query variable.
* **Line 28**: A function that takes the query result as input (array of tasks) and returns a single task. This task is used as the initial value of the form.
* **Line 33**: A function that takes form data and converts it into mutation variables. This function is called when a user submits the form.
* **Line 57**: We tell the GraphQL client to fetch data for our list query when the mutation is successful. If we don't do this, even after we successfully update a task, going back to the list screen will show old data. This is because Apollo will show data from its local cache. By retching a query we update the local cache.

{% code title="src/components/EditTaskForm/index.ts" %}

```typescript
export * from './EditTaskForm';

import { EditTaskForm } from './EditTaskForm';
export default EditTaskForm;
```

{% endcode %}

### Step 4: Add Form to Screen

Let's add our form to the `EditTaskScreen` component:

{% code title="src/screens/EditTaskScreen/EditTaskScreen.tsx" %}

```typescript
import { useNavigation } from '@bluebase/core';
import React from 'react';

import EditTaskForm from '../../components/EditTaskForm';

export const EditTaskScreen = () => {
	const { getParam } = useNavigation();
	const taskId = getParam('taskId', null);

	return (
		<EditTaskForm id={taskId} />
	);
};

EditTaskScreen.displayName = 'EditTaskScreen';
```

{% endcode %}

When you run the app, you should results similar to the screenshot below:

![Web](/files/jNdWmKryGtxMKFF6YZ5v) ![iOS](/files/Zmk7Ld9DQmMBmZppjTD1)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bluebase.gitbook.io/core/tutorial/4.-crud-operations/4.3-updating-tasks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
