Closed7
AmplifyのDataStore(js)のハマリどころ
リレーションは慎重に
AmplifyのDataStoreはリレーションの親が削除されると、子もカスケード削除される。
1対1などは、リレーションのどちらにつけてもよいように感じるかもしれないが、間違って本来の子側にいなるべき方につけてしまうと、消えてほしくないデータが消えてしまう。
many to many リレーションはテーブルを新しく作ってるぽい
DataStoreの初期クラウド同期
初期クラウド同期は全てのテーブルをフルスキャンで持ってくる。
dyanmodbはクエリとスキャンで値段が変わる。なるべく、クエリになるように。
DataStoreの初期クラウド同期終わる前にDataStore.queryすると空のデータしか入っていない。
これはDataStoreのクエリが以下のような仕様だから。
- DataStoreは初期化時にクラウド同期を行い、ローカルのIndexDBと同期させる。
- DataStoreのクエリはローカルのindexDBに対して行われる。
- アプリを初めてそのブラウザで使った場合、クラウド同期が終わるまで、indexDBが空になる。
- あるページを表示する際に、useEffectでDataStoreのクエリを叩くが、クラウド同期が終わっていないばあ、nullになってしまう。
コレに対応するためには2通りの方法があるとされるが、実践的に、つかえるのはほぼ一つ。
- イベントリスナーでDataStoreがreadyになってから、クエリを叩く
- DataStore.queryの代わりにDataStore.obserbeQueryを使う
1つ目の方法は、reactのライフサイクルとDataStoreのライフサイクルが一致しないので、うまくいかなくなるときがちょこちょこでてきた。
2つめの方法は、初回がnullでも同期がおわればsubscribeが発火するので、うまくいく。
useEffect(() => {
if (!corporationId) return;
const sub = DataStore.observeQuery(Corporation, (c) =>
c.id.eq(corporationId)
).subscribe(({ items }) => {
setCorporation(items[0] ?? null);
});
// NOTE: return sub.unsubscribeとするとうまくいかない
return () => sub.unsubscribe();
}, [corporationId]);
useEffectのreturnにunsubscribeを渡すとき、直接関数を渡してはいけない
good
useEffect(() => {
if (!corporationId) return;
const sub = DataStore.observeQuery(Corporation, (c) =>
c.id.eq(corporationId)
).subscribe(({ items }) => {
setCorporation(items[0] ?? null);
});
// ⚠ここに注意
return () => sub.unsubscribe();
}, [corporationId]);
bad
useEffect(() => {
if (!corporationId) return;
const sub = DataStore.observeQuery(Corporation, (c) =>
c.id.eq(corporationId)
).subscribe(({ items }) => {
setCorporation(items[0] ?? null);
});
// ⚠ここに注意
return sub.unsubscribe;
}, [corporationId]);
以下のようなエラーが発生する。
Unhandled Runtime Error
TypeError: Cannot read properties of undefined (reading ‘_state’)
DataをAmplifyStudioで定義するさいに、CustomTypeに!IDをつけるとよくわからないことになる
クラスを生成する際に、TypeScriptの型エラーにひっかかる。
DataをAmplifyStudioで定義するさいに、CustomTypeでidという名前のキーをつかうとよくわからないことになる。
CustomTypeではidという名前ではないものを使いましょう。
このスクラップは2023/10/30にクローズされました