いうライブラリを使ってデータベースアクセスを行うことが推奨されています。使っても良いのですが、今回はまずはシンプルに自分でSQLクエリーを発行してデータベース処理を実装していくことにしました。SQLiteOpenHelperを使うSQLiteデータベースの初期化と接続の管理を行うには、SQLiteOpenHelperを継承したクラスを作成するのが便利です。DatabaseHelper.java---テーブル名、カラム名などの固定文字列は、後述するWordsRepositoryクラス内に定数として定義してあるので、二重で定義しないようにそちらを参照しています。メソッド内で必要なSQLを発行する処理を実行します。今は最初のバージョンなのでまだ何も実装していません。アプリケーション全体を通してデータベース接続を保持するでは、上で作成したDatabaseHelperクラスをどのように使うかを見てみましょう。オープンすると、tryを抜けたときに自動でクローズしてくれるので便利ですね。getWritableDatabase()メソッドを呼んでも構わないのですが、この方法だとデータベースのオープン/クローズ処理が毎回行われることになります。今回のサンプルアプリケーションでは毎回データベース接続をオープン/クローズするのではなく、「カスタムアプリケーションクラス」を使ってアプリケーション全体を通してデータベース接続を保持する方法を使うことにします。MyApplication.java---Applicationクラスのインスタンスはアプリケーションのプロセスが動いているかぎり破棄されることはないので、このクラス内のインスタンス変数として変数を宣言しておけばアプリケーションのどこからでも共通に使うことができます。今回はこれを利用してDatabaseHelperのインスタンスをApplicationクラスで保持することにしました。getDb()というメソッドが初めて呼ばれたときにデータベースをオープンします。呼ばれるので、このタイミングでデータベース接続をクローズしています。カスタムアプリケーションクラスが起動時に正しく呼ばれるようにするには、マニフェストファイルでクラス名を指定しておく必要があります。リポジトリクラスを使ってデータベース処理を一箇所にまとめる次に、実際にデータベースに対してSQLクエリーを発行してデータを取得したり更新したりする処理を実装します。これらの処理はテーブル単位で実行されることが多いので、その単位で「リポジトリクラス」を作ってまとめるのが良いでしょう。いうクラスを作って単語データに関するデータベース処理を記述しました。tryの括弧内でCursorを生成することで自動的にcloseされる。idで指定された単語を返す。idが0の場合は新規インスタンスを生成して返す。idが見つからない場合はnullを返す。tryの括弧内でCursorを生成することで自動的にcloseされる。主キーで絞っているため結果は1行か0行かのどちらかなのでwhileでループする必要はない。idが0の場合は新規追加、0以外の場合は更新処理を行う。idで指定された単語を削除する。単語が見つからない場合は何もしない。args);}今回はSQLiteデータベースの使い方について見てみました。0.1が動くようになりました。ここまでのソースコードは下のURLで公開していますので良ければプロジェクト全体をクローンして動かしてみてください。今回は単語一覧画面の実装方法を詳しく見てみましょう。ListViewの使い方このリストでは、1行に「英語」と「覚えたフラグ(チェックマーク)」の2つの項目を表示したいので、カスタムアダプタを実装しました。WordListViewAdapter.java---ListViewとカスタムアダプターの実装方法はほぼ決まりきったイディオムのようなものなので、ひとまずこれはこういうものとして覚えておけば良いのではないかと思います。ちなみに最近のAndroidではListViewよりもRecyclerViewを使う方が推奨されているようです。ListViewと実装方法においてそれほど大きな違いはなさそうですが、こちらも一応確認しておきたいところです。SQLiteデータベースの使い方についてまとめたいと思います。画面遷移、アクティビティのライフサイクルなど今回から3回に分けてAndroid用の単語帳アプリを作って行こうと思います。0.1として最低限の機能を実装してみます。単語一覧(英語のみ表示。覚えたものにはチェックマークを表示。)単語確認(英語・日本語を表示。する画面は以下の4画面ですが、新規登録と編集・削除は同じアクティビティなので実質的には3画面になります。ソースコードhttps://github.com/makotoishida/flashcards-android/tree/blog-v0.1実装する上でポイントになる点としては、大まかに分けて以下の6つがあります。以下にそれぞれのポイントについて簡単にメモして、参考になりそうなリンクなどを紹介していきます。様の説明が大変分かりやすかったので、以下の説明で特にたくさんリンクさせていただきました。ConstraintLayoutによるレイアウト従来通りのRelativeLayoutやLinerLayoutを入れ子にして画面を作成する方法でも良かったのですが、どうせなら新しいバージョンで推奨されているやり方を使おうと言うことで、ConstraintLayoutを使って画面レイアウトを作成しました。この方法だとほとんど入れ子構造を使わずにフラットな構成でウィジェット同士の相対的な位置関係を定義することでレイアウトが出来るので、慣れれば確かにこちらの方が効率が良いかも知れません。Studioのレイアウトエディタを使いこなせるようになればドラッグ&ドロップで画面をデザイン出来るので、かなり強力ですね。下の動画を観ればおおよその使い方は分かると思います。Layoutはこれだけ知っておこう3https://www.youtube.com/watch?v=AzkYt6W73uQ🎬[Android]ConstraintLayoutでレイアウトを作成する場合の注意点https://www.youtube.com/watch?v=vfL7fp2RTC0公式のガイドも必読ですね。ボタンを画面上部のActionBar内に表示する方法です。5以降らしいですが)のAndroidではActionBarではなく「Toolbar」を使うほうが何かとメリットが大きいようです。Qiitahttps://qiita.com/kobakei/items/f17019f8b0a88c8e57f4ただ今回のサンプルでは特に不都合は無かったのでActionBarを使って実装しました。デベロッパーhttps://developer.android.com/training/appbar/setting-up?hl=jaまた単語の新規登録と編集で同じアクティビティを使っていますが、新規登録の場合はActionBar内の「削除」メニューを非表示にする制御を行っています。画面遷移の実装方法Androidでの画面遷移を上手く制御するためには、アクティビティの「スタック」の概念をしっかりと理解しておく必要があります。現在のアクティビティを「終了」する必要があります。元の画面に遷移してしまうと、スタックの上にさらに新しいアクティビティのインスタンスが積まれることになります。C)を開いたあとで、(Bを飛ばして)一気に最初の画面(A)に戻りたいという場合には、ちょっと工夫が必要になります。単語編集(C)と遷移した状態で、単語が削除されたらBではなくAに戻すためにこの方法を使いました。いう画面遷移が可能になります。WordListActivity.class);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);startActivity(intent);}詳しくは下のサイトを参照してください。Qiitahttps://qiita.com/naoty_k/items/f733ff8a69a141331bba次の画面にデータを渡す単語一覧画面から単語確認画面に遷移するケースでは、画面間で「どの単語がタップされたのか」という情報を受け渡す必要が出てきます。メソッドを使って渡したいデータをインテント内に詰め込むことで実現出来ます。メソッドを使って詰め込まれたデータを取り出します。渡されたインテントから単語IDを得る。指定された単語のデータをデータベースから取得して表示する。おこなっていますが、これは単語一覧画面から開かれたときだけでなく単語編集画面から戻ってきた場合にも単語の表示を更新したい(=編集後の最新の値を反映したい)ためです。アクティビティがスタックの先頭に来て画面に表示される度に毎回呼ばれます。Android用のアプリケーションを開発する上では、このようにアクティビティのライフサイクルを理解することが非常に重要になります。これについては下の動画が大変分かりやすいのでオススメです。Activityのライフサイクルについて書きました。ListViewの使い方についてまとめたいと思います。Chromeでアクセス出来ていたのに急に出来なくなりました。表示されるエラーメッセージはこんな感じです。今までは、このメッセージが出ても下の方に「危険を承知で開く」という意味のリンクがあってそこをクリックすれば続行出来ました。試しに古い方の開発マシンからやってみると、確かにそのようになっていてそちらでは開けます。マシンが変わっただけで開けなくなったということは、何か新しいマシン上で設定が足りていないのかな、と思って調べてみたところ、下の方法で解決したのでメモしておきます。「Security」を開きます。Access」アプリが開きます。(直接このアプリを開いた方が早かった。AccessアプリのCertificatesの中に該当のサイトの証明書があればそれをダブルクリックします。Trust」にしてこの画面を閉じればOKです。この後、ブラウザで該当のURLを開くと、いつも通りにセキュリティの警告が出ますが、一番下の「危険を承知で開く」という意味のリンクをクリックすればサイトが開きます。追記:デバッグ用にローカル環境(localhost)でサイトを動かしている場合は上の方法では上手く行かないかも知れません。その場合は、下の方法を試してみてください。作者さんのブログに書かれているとおりです。状態が何であろうと、日本語を入力したいときは「かな」英語を入力したいときは「英数」を押せばよい所です。状態を気にしなくてもよいので、とても楽なのです。”「左でOFF、右でON」これに慣れるともうトグル方式には戻れません。ちなみに、「英語配列」のキーボードでの話です。「alt-ime-ahk」を使います。Win+Rキーから「shell:startup」と入力して開くフォルダにExeファイルへのショートカットを作成しておけば、ログイン時に自動的に起動してくれます。この設定をしてから、英語キーボードで毎回「ALT+`」で切り替えていたのが「どれだけ時間の無駄だったのか」を痛感しました。Linuxでの設定Mozcでは上手く行かないので、「Fcitx」で設定します。「Karabiner-Elements」を使います。普通に設定すると左右のCommandキーで切り替え可能になります。私はさらにCommandキーに加えて左右のOptionキーでも切り替わるように設定を追加して使っています。するとWindowsやLinuxと共通になるので便利です。right_optionに変更すればOptionキーで切り替え可能に。MacでOptionキーのアサインを変えてしまうと「Optionを押しながらメニューをクリック」した時の挙動が変わってしまうことに気付いたので、やっぱりMacではこの設定はやめて左右Commandキーで切り替えることにしました。LinuxではALTキー、MacではCommandキーという点が異なりますが、「左でOFF、右でON」というのは共通しているので、ひとまずこれで良しとしています。フロントエンドの間でスキーマ定義が半自動的に同期される仕組みがあるというのは便利だな〜と思ったので、そのために使えそうなライブラリを調べました。バックエンドとフロントエンドの両方のプロジェクトで型定義が共有される、という状態にすることです。いうライブラリでした。これは、データベースからテーブルのスキーマを読み取って、TypeScriptの型定義を生成してくれるというもののようです。サンプルコードやこちらのブログ記事を見ても分かるとおり、このライブラリは特にORMのようなものを介さずに自分で直接SQLクエリーを書いてデータベースにアクセスしたいという場合に向いているようです。利用して生成した型定義を使うことができそうです。Prisma専用のスキーマ定義ファイルからTypeScriptの型定義を生成します。このPrismaスキーマをデータベースから自動生成するワークフローと、まず自分でPrismaスキーマを書いて、それをマイグレーションでデータベースに反映するワークフローの2種類をサポートしているそうです。DBからPrismaスキーマを生成PrismaスキーマからDBに反映ただ、こちらのNext.jsでのサンプルを見た感じでは、データベース⇔バックエンドの間では型定義の同期が取れていますがフロントエンド側まではそれが共有されていません。個々のReactコンポーネントのPropsについてはそれぞれに型定義をおこなっているようです。フロントエンド側にまで型定義を共有出来る方法があるのかどうかについてはよく分かりませんでした。いうCLIツールを組み合わせるとデータベースからTypeORM用のモデルクラスを生成することが出来るようです。いうCLIツールが見つかりました。採用することが決まっている場合は、こちらの組み合わせも良いかも知れません。Sequlize向けに生成されたモデルクラスをそのままフロントエンド側で参照してReactコンポーネントなどで使えるかというと、それは厳しいのではないかと思います。「DBから生成した型定義をバックエンドからフロントエンドまで共通で使いたい」と書きましたが、結局よく考えてみると、1バックエンド側でDBアクセスをするための型(テーブル単位)2APIのインターフェースとしての型(ユースケース単位)3フロントエンドのコンポーネント間でやり取りするための型(UI部品単位)はそれぞれに用途が異なるので完全に同じものを使い回すというようなことは現実的ではなさそうです。123の中でもカラム単位で見れば共通の定義を抽出して参照することは可能ではないかと思います。変更されたというようなケースでは、カラム単位で共通の型定義を参照していれば、一箇所が(コマンド一つで半自動的に)変更されれば(バックエンド、フロントエンド含めて)それを参照している全ての箇所がコンパイル時にエラーとなって容易に修正出来るようになるというイメージです。一度試してみる価値があるかも知れないと思いました。Proにつないで使っています。打ちやすくて快適なのですが、長い間解決できずに困っている問題がありました。使ってWindowsマシンを操作しているときに、Homeが「Windows+左矢印キー」、Endが「Windows+右矢印キー」として伝わってしまい、アプリケーションのウィンドウがいきなり画面の左半分にリサイズされたり右半分にリサイズされたりしてしまう、というものです。このような問題は起こりません。使ったときにだけ起きる問題です。含められていないのが原因のようです。除外対象に含めれば良いのか分からなかったのですが、今日は長い間避けて通ってきたこの問題にようやく時間をとって真剣に向き合うことにしました。試行錯誤すること1時間、ついに解決策を発見したのでメモしておきます。]の配列に"^com\\.google\\.Chrome\\.app\\.*",の行を追加すればOKです!(HomeキーとEndキーでそれぞれに設定があるので2箇所とも追加します。)検索して見つけた一部のサイトでは、"^com\\.google\\.Chrome\\.app",と書かれていたのですが、これだと上手く行かず、末尾に「\\.*」を追加することで正しく除外されるようになりました。なく「全てのChromeアプリ」が除外対象になると思います。不都合がある場合はそれぞれのChromeアプリ固有のIDを調べて個々に指定する必要があります。Identifierの値は、Karabiner-Elementsに付属の「EventViewer」を起動すれば簡単に調べることが出来ます。DoddsさんのReactやJavascriptに関する解説を読んだり観たりしていて、とても参考になっていたため。今回のコースはそのKentさんが何年にもわたって数々の有料セミナーなどで教えてきた経験を元に作成された、渾身の作ということなので、まず期待はずれになることはないだろうと確信が持てました。Library」の作者でもあります。ブログを読むと、初めてソフトウェア開発者として職を得たきっかけ、Facebookからのオファーを断ってPayPalに入った経緯、PayPalでの仕事内容、AngularからReactに軸足を移した経緯や、人に教えることへの情熱などがよくわかります。Egghead.ioでおすすめのコースKentさんのコースに興味を持たれた方は、まずはEgghead.ioで下の動画レッスンなどを視聴してみてはいかがでしょうか。使ってJavaScriptアプリケーションを書いているときに、async/awaitを使おうとすると下のエラーが出ました。defined調べたところ、次のサイトに解決策が載っていました。defined対処法1ブラウザを比較的新しいものだけに限定して構わないのであれば、次の方法が簡単です。package.jsonに以下を追記します。2017-06"]これでasync/awaitを使ってもエラーが出なくなります。対処法2もう一つの対処法としては、「regenerator-runtime」パッケージをインストールするというものがあります。'regenerator-runtime/runtime';として読み込みます。バンドルサイズが25KBほど増えてしまうようですが、こちらの方法でもエラーが出なくなります。古いブラウザもサポートする必要がある場合はこちらを使うことになると思います。APIで任意のデータを保存する前回はReactアプリにGoogle認証を組み込む方法を試しました。Driveに保存することに挑戦してみました。完全にブラウザのみで動作するReactアプリケーションなので、バックエンドサーバは不要です。Netlifyなど静的サイトのホスティングサービスを使ってデプロイすることが可能です。Drive内の所定のフォルダからファイル一覧を表示。ファイル名がクリックされるとその内容(テキストデータ)を表示。Driveにテキストデータを保存。いうことを行っています。認証状態とアプリケーション固有の状態を分けて2つのContextプロバイダーで別々に共有するようにします。Keyを作成しておいてください。Driveにアクセスする処理を「google-api.js」に記述します。ファイル削除などの関数をエクスポートしています。アップロード処理がなかなか動かず苦労しましたが、最終的には下のサイトの情報にしたがってMultipart形式でPOST(更新のときはPATCH)リクエストを送ることで解決しました。tanaikeまたファイルの内容を取得する方法も最初は分からず試行錯誤しました。こちらは下のURLにGETリクエストを送ることでダウンロード出来ました。https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&source=downloadUrlもちろんリクエストヘッダーにはGoogle認証で得られたアクセストークンを付加する必要があります。いう定数で定義していますが、これはユーザーが任意のフォルダ名を指定出来るようにした方が便利ですね。Driveへのデータ保存が出来るということが分かりました。単純なテキストではなく例えばJSONを保存すれば、ある意味簡易的なデータベースとしても使えるかも知れませんね。何よりアプリの開発者側で保存先のデータベースやストレージを用意する必要が無いのが魅力的です。今回作成したアプリケーションのソースコードはこちらにあります。共有2020年6月14日ReactのSPAアプリケーションでContextとHooksを使ってGoogle認証を実装するReactのSPAアプリケーションにおいて、ContextとHooksを使うことでGoogle認証の処理をラップして利用するというサンプルを作成しました。編集するWebアプリケーションでGoogle認証を利用するための最もシンプルなサンプルコードがこちらにあります。public/index.htmlを編集します。上のサンプルコードの中でReactアプリで必要になるのはGoogleのスクリプトを読み込んでいる行だけなので、その部分をコピーしてheadタグ内に挿入します。Appの場合これがあるとスクリプトが実行されるタイミングの関係で上手く動かないので削除しています。ファイルを作成して値を設定しておきましょう。Appの規約上「REACT_APP_」から始まる必要があるので注意してください。ClientIdを環境変数に持たせておくことによって、本番用、ステージング用など、ビルド環境に応じて柔軟に変更することが出来るようになります。APIを実際に呼び出す際に使う関数をこのファイルにまとめておきます。signOut()の3つの関数をエクスポートしています。------src/auth-state.jsファイルを作成する上のgoogle-auth.jsに定義した関数をReactアプリ内で使うためのContextプロバイダーとフックを提供するファイルになります。内部的にはuseReducerを使って認証状態を管理していますが、それはファイル内に隠蔽して外部へはAuthProviderコンポーネントとuseAuthStateフックをエクスポートしています。オブジェクトの2要素配列となっています。AuthProviderコンポーネントでアプリをラップする。任意のコンポーネント内でuseAuthStateフックを使って認証機能にアクセスする。);}今回作成したアプリケーションのソースコードはこちらにあります。https://github.com/mikehibm/googleauth-react-202006以上、ReactのSPAアプリケーションにおいて、ContextとHooksを使ってGoogle認証の処理をラップするサンプルでした。Driveに保存するということに挑戦したいと思います。読み上げ機能は目に優しい最近、ブラウザでニュースを読む時にMacの音声読み上げ機能を使うと、「目を閉じていてもニュースが頭に入ってくる」ことに気付きました。これは慣れるとかなり便利。なんと言っても目の疲れが大幅に軽減できることが最大の利点です。Speaking」を選べば読み上げ機能を使うことは可能です。アクセシビリティの設定で任意のショートカットキーを設定することも出来ます。一つの言語しか読み上げさせる必要がないのであれば、これで大丈夫です。複数の言語を使い分けたい場合は、これだと読み上げに使用する言語(音声)をその都度選ぶことが出来ません。日本語の音声を設定している状態で英語の文章を読み上げさせても、カナカナ読みの変な発音でしか読まれません。逆に英語の音声が選択されている状態で日本語を読み上げさせようとしても、上手く発音してくれません。選択されている文章の言語によって読み上げに使う音声を切り替える必要があるわけです。これが出来るように今回設定した方法を、以下にメモしておきます。選んで、ドラッグアンドドロップで追加します。読み上げに使う言語に対応した音声を選んで、後から分かる名前を付けて保存します。これを、使いたい言語の数だけ繰り返します。Actionが表示されます。ActionのチェックをONにして、好きなショートカットキーを設定すれば完了です。英語読み上げとしています。片手ですぐ押さえられる組み合わせが良いと思います。Actionが追加されているのが分かります。Analyticsを追加する(Next.js)まずは、Firebaseの管理画面から、該当のプロジェクトでAnalyticsを有効化します。アナリティクスを使ってみるここではNext.jsからエクスポートした静的サイトを例にします。全てのページで共通に含まれる部分で、下のようにHeadコンポーネントを使ってscriptタグを埋め込みます。要は下の赤字部分の3行のscriptタグがHTMLのhead部分に含まれるようにすれば良いということですね。);}次に、下のドキュメントの通りにイベントを送信する必要があります。「use-send-screenview.js」という2つのファイルを作成しました。pages/index.jsから呼び出すことでAnalyticsにイベントを送信します。deployでデプロイしてサイトを更新します。更新後のページを開くと、数秒でAnalyticsの画面にイベントが表示されるのが確認出来ます。Hostingでホスティングするまずは公式のドキュメントにしたがってNext.jsのアプリケーションを作成しましょう。Next.jshttps://nextjs.org/learn/basics/create-nextjs-apppackage.jsonファイルのscriptsセクションに下記を追加しておきます。outフォルダに結果が出力されるのを確認します。CLIを初期化します。initカーソルキーで「Hosting」を選択してスペースキーを押し、Enterで確定です。Firebaseの管理画面でまだ「プロジェクト」を作成していない場合は、プロジェクトIDと名称を入力して新規作成します。使われているIDを入れてしまうとエラーになるので、ユニークなIDを入力しましょう。アップロード対象のフォルダを聞かれるので、デフォルトの「public」ではなく「out」を指定します。complete!」と表示されれば完了です!慣れれば3分もかからずに出来てしまいますね。Functionsを使ったりするような場合も、下のドキュメントの通り設定すれば決して難しくはありません。使用した動的コンテンツの配信とマイクロサービスのホスティング本当に便利な世の中になったものです。Hostingでなくても良いのであれば、もちろんNext.jsの開発元であるVercel(旧Zeit)社のサービスを使うのが一番簡単でオススメです。https://vercel.com/こちらであれば、静的サイトでなくSSRありのサイトであっても、またバックエンドのAPIが必要な場合でも、何も考えずにデプロイしてしまえばあとはサービス側で上手くやってくれるみたいなので、こちらも素晴らしいと思います。共有2020年5月4日ReactでSVGファイルをコンポーネントとしてレンダリングするegghead.ioのレッスンを観ていて良さそうなものがあったので、メモしておきます。ドキュメントにも記述があります。Appで作ったReactアプリケーションでは画像ファイルを下のようにインポートしてコンポーネント内で参照することが出来ます。/>;}もちろん画像の形式がSVGであっても同様です。/>;}ただ、SVG形式の場合はインポートの仕方を下のように変えるとReactコンポーネントとしても使えるようになるそうです。imgタグではなく、svgタグになります。svgタグになってうれしい点は、SVG内の個々の要素(図形)をCSSでコントロール出来るようになることです。線の色や太さを変えたり、アニメーションを付け加えたりすることが可能になります。下の例では、Reactロゴのpathエレメントの部分のみ点線にして、さらに点線のオフセットをアニメーションで動かしています。}}実行するとこんな感じになります。APIを構築する前回はユーザー認証機能を付けましたが、まだデータの永続化が出来ていないのでTodoアプリとしては未完成です。APIを追加してデータをデータベースに保存出来るようにします。現状を確認すると、下のようになっています。下のコマンドでAPIカテゴリを追加します。選ぶように言われます。Web上で見つかる情報にはGraphQLを使ったものが圧倒的に多いように思いますが、ここではあえてRESTを選びます。DynamoDB上に作成するテーブル名まで入力すると、次に作成するカラム情報の入力になります。ドキュメントをざっと読んだところ、DynamoDBでは基本的に1アプリケーションで使うテーブルは出来るだけ少ない方が望ましいらしく、「1テーブルで済ませられればそれが最も良い」との事です。長年リレーショナルデータベースに馴染んだ身としてはなかなか目から鱗な考え方です。DynamoDBでのスキーマ設計の勘所は、「パーティションキー」と「ソートキー」および「グローバル・セカンダリインデックス」「ローカル・セカンダリインデックス」を上手く使うことにあるようです。)この辺り、非常に奥が深そうで面白いのですがとりあえず今はシンプルなTodoリストアプリを作りたいだけなので、極力簡単な方法で行きたいと思います。パーティションキーを「pk」、ソートキーを「sk」とし、3つ目のカラムはmap型で「data」としておきました。map型にはJSONを格納できるので、こうしておけば後からの仕様変更にもある程度柔軟に対応することが可能になるかと思います。パーティションキーとソートキーを何にするかというのは、アプリケーションの要件によって大きく変わる部分で、開発効率にも大きく関わってきます。"todo:"というプリフィックスを付加して格納することにしました。することでユーザーのidが分かればそのユーザーに属するタスクの一覧を簡単に取得することが出来るようになります。始まるという条件で検索することになります。DynamoDBではパーティションキーは完全一致でしか検索出来ませんが、ソートキーは部分一致や範囲検索が可能なので、このようなクエリーが可能になります。以外のものにすれば対応出来ます。して保存すれば、簡単にそのレコードを一意に指定して読み出す事が出来ます。1アプリケーションで一つのテーブルしか使わない、というのはこのように2つのキー(およびセカンダリインデックス)を上手く使って複数の種類のデータを保存する、ということになるのかなと思います。カラム設定の入力が終わると、テーブルへのアクセス権の設定をするか聞かれるので、認証していないユーザーはAPIへのアクセスが出来ない様に設定しておきます。実行して、追加した設定をAWS側に反映します。完了するとAWS側では下記のリソースが作成されています。DynamoDBこれらのうち、Lambda関数は自動生成されたコードだと上手く動かず、何をしているのかを理解した上でアプリケーションの要件に合わせてそこそこ手を加える必要がありました。false}}という形になっています。Gatewayから受け取ったオブジェクトをDynamoDBのスキーマに合った形式に適宜変換してから保存しています。次はReactアプリの方を変更して行きます。この辺りのドキュメントを見ながらAPIへのアクセス処理を実装します。DELETEでLamdaで作成してあるAPIにアクセスすることが出来るので、各アクションからこれらを適宜呼び出しています。useReducer)を使って作っています。/services/todo-service.js----------ここまででなんとかシンプルなTodoリストアプリが完成しました。DynamoDB以外の任意のデータベースを使うことも可能。