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 . 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.
src/components/EditTaskForm/UpdateTaskMutation.graphql.ts
Copy 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
}
}
}
` ;
Step 2: Generate Typings
We will now generate typescript interfaces for our GraphQL API. Execute the following command:
This will update the file src/graphql-types.ts
.
Step 3: Create Form
Create the following component:
src/components/EditTaskForm/EditTaskForm.tsx
Copy 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' ;
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.
src/components/EditTaskForm/index.ts
Copy export * from './EditTaskForm' ;
import { EditTaskForm } from './EditTaskForm' ;
export default EditTaskForm;
Step 4: Add Form to Screen
Let's add our form to the EditTaskScreen
component:
src/screens/EditTaskScreen/EditTaskScreen.tsx
Copy 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' ;
When you run the app, you should results similar to the screenshot below: