Fusic Tech Blog

Fusicエンジニアによる技術ブログ

React + AppSyncでデータの追加(Mutation)を実行する
2024/03/29

React + AppSyncでデータの追加(Mutation)を実行する

どうもこんにちは。Fusic小原です。前回はGraphQLでQueryを実行しました。その続きで今回はAppSyncにMutationをリクエストしてみようと思います。

前回の記事 ReactからAppSyncへQueryを投げる

はじめに

GraphQLではSQLみたいに検索処理、追加処理などそれぞれの機能があります。 Queryが検索系、Mutationが編集系の処理になります。

Mutationについてもう少し詳しく

Mutationは先程書いたとおり編集系の処理を行います。編集系というと追加処理、編集処理、削除処理になります。なのでSQLでいうとinsert、update、delete処理になります。

AppSyncでMutation処理を受け付けると、その処理をデータソースに渡します。今回は前回同様データソースはDynamoDBを使いましょう。DynamoDBに対してデータの追加、編集、削除処理を行うようAppSyncのResolverに記載していきます。

Mutationの実装

では早速Mutation処理を実装していきたいと思います。 前回の続きで自分が所属しているチームで使ってるコンディションシートの実装内容をもとに進めていきましょう。

追加処理

まずはフロント側の実装を見ていきましょう。 GraphQLでQueryと同様、Schemaを定義します。

import gql from 'graphql-tag';

export default gql`
mutation createCondition($condition: CreateConditionInput!) {
 createCondition(input: $condition) {
  id
  user_id
  date
  physical_state
  physical_note
  work_state
  work_note
  work_after
  leave_time
 }
}`;

ここではcreateConditionっというSchemaを定義します。引数であるconditionには追加するコンディションのデータをいれます。

これと同様の定義をAppSync側にも定義します。GraphQLではフロント側(React)とバックグラウンド側(AppSync)に同様のSchemaを定義する必要があります。

CreateConditionInputは構造体みたいにいくつかのフィールドが定義されております。 後から出てきますので、ここで定義を見ておきましょう。

input CreateConditionInput {
	user_id: String!
	date: AWSDate!
	physical_state: Int
	physical_note: String
	work_state: Int
	work_note: String
	work_after: String
	leave_time: AWSTime
}

普通の構造体とほぼほぼ同じですね。少し違うのが!の部分です。これは!を指定したフィールドが必須項目っということを表しています。なのでuser_iddateは必ず追加しないと行けないっということです。 このリクエストをAppSyncが受け取り、ResolverでDynamoDBに入れるよう修正します。

では次にAppSync側のResolverを見てみましょう。

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

ここで大事なのは "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input), の部分になります。$ctx.args.inputが引数のinputのデータが入っています。

そのデータを$util.dynamodb.toMapValuesJson関数に渡しDynamoDBへ入れれる形に整形します。そのデータをResolverのattributeValuesに指定するとDynamoDBへそのデータが追加されています。 では実際にこのSchemaを使ってリクエストを投げましょう。

import React from 'react';
import { connect } from 'react-redux';
import CreateCondition from '../components/createCondition.jsx';
import { compose, graphql } from 'react-apollo';
import CreateConditionMutation from '../queries/createConditionMutation.js';

class CreateConditionContainer extends React.Component {
  createCondition(condition) {
    this.props.onCreate(condition);
  }
  render() {
    return(
      <Hero>
        ・・・
          <CreateCondition
            user={ this.props.user }
            onCreate={ this.createCondition.bind(this) }
          />
        ・・・
      </Hero>
    );
  }
}

export default connect(
  mapStateToProps,
)(compose(
  graphql(CreateConditionMutation, {
    props: (props) => ({
      onCreate: (condition) => {
        props.mutate({
          variables: {
            condition: condition
          }
        })
      }
    }),
    options: (props) => ({
      update: (proxy, { data: { createCondition: condition } }) => {
        props.history.push("/conditions/daily?date=" + condition.date);
      }
    })
  }),
)(CreateConditionContainer));

CreateConditionContainerコンポーネント内でリクエストを送りレスポンスを受け取ります。 では一つずつ見ていきましょう。

graphql(CreateConditionMutation, {
    props: (props) => ({
      onCreate: (condition) => {
        props.mutate({
          variables: {
            condition: condition
          }
        })
      }
    }),

Query同様graphqlの第一引数にGraphQLのSchemaを定義します。 第二引数にこのリクエストのオプションをセットします。 propsのところで関数を定義します。ここで指定した関数はコンポーネント内から実行することができます。ここではonCreateをコンポーネントから実行することができます。onCreateを実行しprops.mutateを実行します。引数のvariables要素にSchemaの引数となる値を入れます。

オブジェクトのconditionにコンディションとして追加するデータを入れます。onCreate関数の引数のconditionは追加するコンディションのデータになります。

props.mutateでAppSyncへリクエストを送り、レスポンスが返ってきたらoptionsupdateが呼ばれます。では実際の実装を見ていきましょう。

    options: (props) => ({
      update: (proxy, { data: { createCondition: condition } }) => {
        props.history.push("/conditions/daily?date=" + condition.date);
      }
    })
  }),

update関数が呼ばれ props.history.push関数が呼ばれページ遷移します。 update関数の引数であるconditionにはMutationで追加した値が返ってきます。 その値からdateをとりページ遷移をします。 これで無事にDynamoDBへデータが追加されました。

まとめ

Mutation処理自体は他にも更新、削除処理を担っています。それぞれフロント側の実装は追加処理とそこまで変わらないがAppSyncのResolver処理が大きく変わってきます。特に更新処理は少々複雑でしたのでまた次の機会に。

kobaru

kobaru

インフラ好きっ子