Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Choose your framework/language

Gen1 DocsLegacy

Page updated Mar 26, 2026

リアルタイムイベントの購読

このガイドでは、リアルタイムデータ統合を有効にする利点と、これらのサブスクリプションを設定およびフィルターする方法について説明します。また、サブスクリプションの購読解除方法についても取り上げます。

開始する前に、以下が必要です:

With Amplify Data Construct @aws-amplify/data-construct@1.8.4, an improvement was made to how relational field data is handled in subscriptions when different authorization rules apply to related models in a schema. The improvement redacts the values for the relational fields, displaying them as null or empty, to prevent unauthorized access to relational data.

This redaction occurs whenever it cannot be determined that the child model will be protected by the same permissions as the parent model.

Because subscriptions are tied to mutations and the selection set provided in the result of a mutation is then passed through to the subscription, relational fields in the result of mutations must be redacted.

If an authorized end-user needs access to the redacted relational fields, they should perform a query to read the relational data.

Additionally, subscriptions will inherit related authorization when relational fields are set as required. To better protect relational data, consider modifying the schema to use optional relational fields.

リアルタイムリストクエリの設定

リストデータをフェッチする推奨方法は、observeQueryを使用してアプリデータをすべて常にリアルタイムで取得することです。observeQueryをReactのuseStateおよびuseEffectフックと統合するには、次のようにします:

import { useState, useEffect } from 'react';
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';
type Todo = Schema['Todo']['type'];
const client = generateClient<Schema>();
export default function MyComponent() {
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
const sub = client.models.Todo.observeQuery().subscribe({
next: ({ items, isSynced }) => {
setTodos([...items]);
},
});
return () => sub.unsubscribe();
}, []);
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.content}</li>
))}
</ul>
);
}

observeQueryはクラウド内で使用可能なすべてのデータをフェッチしてページネーションします。クラウドからデータが同期されている間、スナップショットには到着したすべてのアイテムとfalseisSyncedステータスが含まれます。同期プロセスが完了すると、ローカルストア内のすべてのレコードとtrueisSyncedステータスを含むスナップショットが発出されます。

トラブルシューティング
リアルタイムイベントとモデルフィールドがない

期待するすべてのリアルタイムイベントとモデルフィールドが表示されない場合は、以下を確認してください。

認可

モデルの認可ルールはユーザーに適切な権限を付与する必要があります。

操作認可
onCreateread OR listen
onUpdateread OR listen
onDeleteread OR listen
observeQueryread OR (listen AND list)

認可ルールが正しい場合は、セッションが期待どおりに認証されていることを確認してください。

セレクションセットのパリティ

リアルタイム更新で表示されるすべてのフィールドは、それをトリガーするミューテーションのセレクションセットに存在する必要があります。ミューテーションは基本的にセレクションセットを介してフィールドを「提供」し、対応するサブスクリプションがそこから選択できます。

これに対処する1つの方法は、両方の操作に共通のセレクションセット変数を使用することです。例えば:

// セレクションセット `as const` を定義すると、型が
// レスポンスオブジェクトに伝播することが保証されます。
const selectionSet = ['title', 'author', 'posts.*'] as const;
const sub = client.models.Blog.observeQuery(
filter: { id: { eq: 'blog-id' } },
selectionSet: [...selectionSet]
).subscribe({
next(data) {
handle(data.items)
}
});
// 更新は同じセレクションセットを使用し、必要なすべての
// フィールドがサブスクライバーに提供されることを保証します。
const { data } = await client.models.Blog.update({
id: 'blog-id',
name: 'Updated Name'
}, {
selectionSet: [...selectionSet]
});

これは、Blogへのすべてのサブスクリプションが同じフィールドサブセットを必要とする場合に適切に機能します。複数のサブスクリプションが様々なセレクションセットを使用している場合は、すべてのBlogミューテーションがすべてのサブスクリプションからのフィールドのスーパーセットを含むことを確認する必要があります。

別の方法として、カスタムセレクションセット全体をスキップできます。任意のモデルの内部生成されたセレクションセットは、デフォルトで操作全体で同じです。トレードオフは、デフォルトのセレクションセットが関連モデルを除外することです。したがって、関連モデルが必要な場合は、遅延ロードするか、別にフェッチするクエリを構築する必要があります。

関連モデルのミューテーション

ミューテーションは関連モデルのリアルタイム更新をトリガーしません。これは、サブスクリプションがセレクションセットに関連モデルを含む場合でも当てはまります。例えば、特定のBlogを購読し、Postが追加または変更されたときに更新を表示したい場合、Blogにサブスクリプションを作成して「機能する」と仮定するのは魅力的です:

// `Blog`の詳細をいくつか取得しているが、主にセレクションセットを使用して
// すべての関連投稿を取得していることに注意してください。
const selectionSet = ['title', 'author', 'posts.*'] as const;
const sub = client.models.Blog.observeQuery(
filter: { id: { eq: 'blog-id' } },
selectionSet: [...selectionSet]
).subscribe({
next(data) {
handle(data.items)
}
});

しかし、Postレコードのミューテーションは関連Blogのリアルタイムイベントをトリガーしません。Postが追加されたときにBlogの更新が必要な場合は、関連するBlogレコードを手動で「タッチ」する必要があります。

async function addPostToBlog(
post: Schema['Post']['createType'],
blog: Schema['Blog']['type']
) {
// まずポストを作成します。
await client.models.Post.create({
...post,
blogId: blog.id
});
// ブログを「タッチ」して、サブスクライバーに再レンダリングを通知します。
await client.models.Blog.update({
id: blog.id
}, {
// サブスクリプションが関連モデルフィールドを探している場合は
// セレクションセットを含めることを忘れないでください!
selectionSet: [...selectionSet]
});
}

リアルタイムイベントサブスクリプションの設定

サブスクリプションは、特定のイベントが発生したときにサーバーがクライアントにデータを送信できる機能です。例えば、新しいレコードが作成、更新、または削除されたときのイベントを購読できます。サブスクリプションは、Amplifyデータスキーマの任意のa.model()で自動的に利用可能です。

import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';
const client = generateClient<Schema>();
// Todoの作成を購読
const createSub = client.models.Todo.onCreate().subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
});
// Todoの更新を購読
const updateSub = client.models.Todo.onUpdate().subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
});
// Todoの削除を購読
const deleteSub = client.models.Todo.onDelete().subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
});
// サブスクリプションからデータ更新の受け取りを停止
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();

サーバー側のサブスクリプションフィルターの設定

サブスクリプションは、サービス側のサブスクリプションフィルターを定義するオプショナルなfilter引数を受け取ります:

import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';
const client = generateClient<Schema>();
const sub = client.models.Todo.onCreate({
filter: {
content: {
contains: 'groceries',
},
},
}).subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
});

すべてのサブスクリプションイベントを取得する場合は、filterパラメータを指定しないでください。

制限:

  • フィルターとして空のオブジェクト{}を指定することは推奨されません。フィルターとして{}を使用すると、データモデルの認可ルールに基づいて矛盾した動作が発生する可能性があります。
  • 動的グループ認可を使用している場合、レコードごとに単一のグループに基づいて認可される場合、サブスクリプションはユーザーが5つ以下のユーザーグループの一部である場合にのみサポートされます。
  • さらに、グループの配列(groups: [String])を使用して認可する場合、
    • サブスクリプションはユーザーが20以下のグループの一部である場合にのみサポートされます
    • レコードごとに20以下のユーザーグループのみを認可できます

サブスクリプション接続ステータス更新

アプリケーションが設定され、サブスクリプションを使用している状態で、サブスクリプションが最終的に確立されたときを知りたい場合があります。また、サブスクリプションが正常でない場合はユーザーに反映することができます。Hubローカルイベントシステムを通じて接続状態の変化を監視できます。

import { CONNECTION_STATE_CHANGE, ConnectionState } from 'aws-amplify/data';
import { Hub } from 'aws-amplify/utils';
Hub.listen('api', (data: any) => {
const { payload } = data;
if (payload.event === CONNECTION_STATE_CHANGE) {
const connectionState = payload.data.connectionState as ConnectionState;
console.log(connectionState);
}
});

サブスクリプション接続状態

  • Connected - 接続され、問題なく動作しています。
  • ConnectedPendingDisconnect - 接続にアクティブなサブスクリプションがなく、切断しています。
  • ConnectedPendingKeepAlive - 接続は開いていますが、予期されたキープアライブメッセージが失われています。
  • ConnectedPendingNetwork - 接続は開いていますが、ネットワーク接続が中断されています。ネットワークが復旧すると、接続はトラフィック処理を継続します。
  • Connecting - 接続を試みています。
  • ConnectionDisrupted - 接続が中断され、ネットワークが利用可能です。
  • ConnectionDisruptedPendingNetwork - 接続が中断され、ネットワーク接続が利用不可です。
  • Disconnected - 接続にアクティブなサブスクリプションがなく、切断しています。
トラブルシューティング
接続の問題の解決と自動再接続

アプリケーションとバックエンドサブスクリプション間の接続は、ネットワーク障害やデバイスがスリープモードに入るなど、様々な理由で中断される可能性があります。サブスクリプションは接続可能になると自動的に再接続します。

オフライン中、アプリケーションはメッセージを失い、再接続時に自動的に追いつくことはありません。ユースケースによっては、アプリがオンラインに戻ったときに追いつく処置を講じたい場合があります。

import { generateClient, CONNECTION_STATE_CHANGE, ConnectionState } from 'aws-amplify/data'
import { Hub } from 'aws-amplify/utils'
import { Schema } from '../amplify/data/resource';
const client = generateClient<Schema>()
const fetchRecentData = () => {
const { data: allTodos } = await client.models.Todo.list();
}
let priorConnectionState: ConnectionState;
Hub.listen("api", (data: any) => {
const { payload } = data;
if (
payload.event === CONNECTION_STATE_CHANGE
) {
if (priorConnectionState === ConnectionState.Connecting && payload.data.connectionState === ConnectionState.Connected) {
fetchRecentData();
}
priorConnectionState = payload.data.connectionState;
}
});
const createSub = client.models.Todo.onCreate().subscribe({
next: payload => // 受信メッセージを処理
});
const updateSub = client.models.Todo.onUpdate().subscribe({
next: payload => // 受信メッセージを処理
});
const deleteSub = client.models.Todo.onDelete().subscribe({
next: payload => // 受信メッセージを処理
});
const cleanupSubscriptions = () => {
createSub.unsubscribe();
updateSub.unsubscribe();
deleteSub.unsubscribe();
}

サブスクリプションから購読を解除

以下を実装してイベントのサブスクリプションから購読を解除することもできます:

// サブスクリプションからデータ更新の受け取りを停止
sub.unsubscribe();

まとめ

おめでとうございます!リアルタイムイベントの購読ガイドが完了しました。このガイドでは、リアルタイムイベントのサブスクリプションを設定し、必要に応じてこれらのサブスクリプションをフィルターしてキャンセルする方法を学びました。

次のステップ

推奨される次のステップには、データの情報アーキテクチャを構築およびカスタマイズし続けることが含まれます。このような作業に役立つリソースをいくつか紹介します: