React Native を使った Amplify のチュートリアルを Typescript で進めたときの備忘録です。
https://docs.amplify.aws/start/q/integration/react-native のチュートリアルを元に Typescript で実装していきます。
以降の章では、チュートリアルのステップ毎に変更した箇所を挙げていきます。
そのため、特に記載がない場合はチュートリアルに従ってください。
このステップは特に変更箇所はないので、チュートリアルに従ってください。
React Nativce のプロジェクトを作成する場合は、次のコマンドに変更します。
npx react-native init RNAmplify --template react-native-template-typescript
index.js を index.ts にリネームすることで、app.json の読み込みがエラーになります。
tsconfig.json に以下を追加して解消してください。
{
"compilerOptions": {
"resolveJsonModule": true, // add
}
}
amplify api push
する際の質問? Choose the code generation language target
は typescript を選択します。
これで graphql ディレクトリに作成されるファイルが typescript 版となります。
amplify mock api
を実行するには Java がインストールされていなければなりません。
今回は AWS ということもあるので、Corretto をインストールします。
macOS の場合、Corretto は brew でインストールできるので、以下のコマンドを実行します。
brew cask install corretto
この章では API の呼び出しを TypeScript で実装するため、いくつか変更を加えていきます。
import React, { useState, useEffect } from 'react';
// aws-amplifyより@aws-amplifyが良い
import { API, graphqlOperation, GraphQLResult } from '@aws-amplify/api';
import { listTodos } from './src/graphql/queries';
import { ListTodosQuery } from 'src/API';
import { createTodo } from 'src/graphql/mutations';
import { StyleSheet, Button, TextInput, View, Text } from 'react-native';
type Todo = {
id: string;
name: string;
description: string;
};
const initialState: Todo = { id: '', name: '', description: '' };
const App: React.FC = () => {
const [formState, setFormState] = useState(initialState);
const [todos, setTodos] = useState<Todo[]>([]);
useEffect(() => {
fetchTodos();
}, []);
function setInput(key: string, value: string) {
setFormState({ ...formState, [key]: value });
}
async function fetchTodos() {
try {
// Unionの戻りをGraphQLResult<ListTodosQueyr>で型アサーションする
const todoData = (await API.graphql(
graphqlOperation(listTodos),
)) as GraphQLResult<ListTodosQuery>;
// Stateの型(Todo[])に合わせて型アサーションをする
const todos = todoData?.data?.listTodos?.items as Todo[];
setTodos(todos);
} catch (err) {
console.log('error fetching todos');
}
}
async function addTodo() {
try {
const todo = { ...formState };
setTodos([...todos, todo]);
setFormState(initialState);
await API.graphql(graphqlOperation(createTodo, { input: todo }));
} catch (err) {
console.log('error creating todo:', err);
}
}
return (
<View style={styles.container}>
<TextInput
onChangeText={(val) => setInput('name', val)}
style={styles.input}
value={formState.name}
placeholder="Name"
/>
<TextInput
onChangeText={(val) => setInput('description', val)}
style={styles.input}
value={formState.description}
placeholder="Description"
/>
<Button title="Create Todo" onPress={addTodo} />
{todos.map((todo, index) => (
<View key={todo.id ? todo.id : index} style={styles.todo}>
<Text style={styles.todoName}>{todo.name}</Text>
<Text>{todo.description}</Text>
</View>
))}
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', padding: 20 },
todo: { marginBottom: 15 },
input: { height: 50, backgroundColor: '#ddd', marginBottom: 10, padding: 8 },
todoName: { fontSize: 18 },
});
export default App;
GraphQL から取得するあたりで型を合わせることが難しく、import するモジュールは基本的に@aws-amplify
を使ったほうがすっきりしていました。
それと型アサーションを多用することで、タイプセーフかつ思い通りに実装できました。
ここまでで、Run locally がうまく動作するはずです。
aws-amplify-react-native
の参照は以下のように src 以下とします。
src 以下は全て TypeScript ファイルになっています。
import { withAuthenticator } from 'aws-amplify-react-native/src'