Skip to content

Instantly share code, notes, and snippets.

@derbuihan
Created April 12, 2023 17:14
Show Gist options
  • Save derbuihan/ff8ff4a1dac9341e923c25b40861e40a to your computer and use it in GitHub Desktop.
Save derbuihan/ff8ff4a1dac9341e923c25b40861e40a to your computer and use it in GitHub Desktop.
Next.jsとAmplify DataStoreを用いたTwiiterアプリのサンプル
import Head from "next/head";
import { Tweet } from "@/models";
import { Authenticator } from "@aws-amplify/ui-react";
import { useEffect, useReducer } from "react";
import TweetForm from "@/components/TweetForm";
import SignoutButton from "@/components/SignoutButton";
import RefreshButton from "@/components/RefreshButton";
import Timeline from "@/components/Timeline";
import { TweetsAction } from "@/types/tweets";
import { DataStore } from "@aws-amplify/datastore";
import { Predicates, SortDirection } from "aws-amplify";
export default function Home() {
const [tweets, dispatch] = useReducer(
(tweets: Tweet[], action: TweetsAction): Tweet[] => {
switch (action.type) {
case "ADD":
return [action.payload, ...tweets];
case "DELETE":
return tweets.filter((tweet) => tweet.id !== action.payload.id);
case "SET":
return action.payload;
default:
return tweets;
}
},
[]
);
useEffect(() => {
(async () => {
const fetchedTweets = await DataStore.query(Tweet, Predicates.ALL, {
sort: (s) => s.updatedAt(SortDirection.DESCENDING),
});
dispatch({ type: "SET", payload: fetchedTweets });
})();
const subscription = DataStore.observe(Tweet).subscribe(async (msg) => {
const { element, opType } = msg;
switch (opType) {
case "INSERT":
return dispatch({ type: "ADD", payload: element });
case "DELETE":
return dispatch({ type: "DELETE", payload: element });
default:
break;
}
});
return () => {
subscription.unsubscribe();
};
}, []);
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<Authenticator>
<TweetForm />
<SignoutButton />
<RefreshButton dispatch={dispatch} />
<Timeline tweets={tweets} />
</Authenticator>
</main>
</>
);
}
import { Button } from "@aws-amplify/ui-react";
import { DataStore } from "@aws-amplify/datastore";
import { Tweet } from "@/models";
import { TweetsAction } from "@/types/tweets";
import { Predicates, SortDirection } from "aws-amplify";
export default function RefreshButton({
dispatch,
}: {
dispatch: (action: TweetsAction) => void;
}) {
const refresh = async () => {
const fetchedTweets = await DataStore.query(Tweet, Predicates.ALL, {
sort: (s) => s.updatedAt(SortDirection.DESCENDING),
});
dispatch({ type: "SET", payload: fetchedTweets });
};
return <Button onClick={refresh}>Refresh</Button>;
}
type Tweet
@model
@auth(rules: [
{allow: owner, provider: userPools, operations: [read, create, delete]},
{allow: public, provider: iam, operations: [read]}
]) {
id: ID!
owner: String
content: String!
}
import { Button } from "@aws-amplify/ui-react";
import { Auth } from "aws-amplify";
export default function SignoutButton() {
const signOut = async () => {
await Auth.signOut();
};
return <Button onClick={signOut}>SignOut</Button>;
}
import { Collection } from "@aws-amplify/ui-react";
import { Tweet } from "@/models";
import { DataStore } from "@aws-amplify/datastore";
import TweetCard from "@/components/TweetCard";
export default function Timeline({ tweets }: { tweets: Tweet[] }) {
const deleteTweet = async (tweet: Tweet) => {
await DataStore.delete(Tweet, tweet.id);
};
return (
<Collection items={tweets} type="list">
{(tweet: Tweet) => (
<TweetCard key={tweet.id} tweet={tweet} deleteTweet={deleteTweet} />
)}
</Collection>
);
}
import { Button, Card, Flex, Heading } from "@aws-amplify/ui-react";
import { Tweet } from "@/models";
export default function TweetCard({
tweet,
deleteTweet,
}: {
tweet: Tweet;
deleteTweet: (tweet: Tweet) => void;
}) {
return (
<Card>
<Heading level={5}>{tweet.content}</Heading>
<Flex>
<Button onClick={() => deleteTweet(tweet)}>Delete</Button>
</Flex>
</Card>
);
}
import { Button, Flex, TextAreaField } from "@aws-amplify/ui-react";
import { useState } from "react";
import { Tweet } from "@/models";
import { DataStore } from "@aws-amplify/datastore";
export default function TweetForm() {
const [tweet, setTweet] = useState("");
const createTweet = async (content: string) => {
await DataStore.save(new Tweet({ content }));
};
return (
<Flex
as="form"
direction="column"
onSubmit={(e) => {
e.preventDefault();
createTweet(tweet);
}}
>
<TextAreaField
onChange={(e) => {
setTweet(e.target.value);
}}
label="create tweet"
labelHidden={true}
isRequired={true}
/>
<Button type="submit">Tweet</Button>
</Flex>
);
}
import { Tweet } from "@/models";
type AddTweetAction = {
type: "ADD";
payload: Tweet;
};
type DeleteTweetAction = {
type: "DELETE";
payload: Tweet;
};
type RefreshTweetsAction = {
type: "SET";
payload: Tweet[];
};
type TweetsAction = AddTweetAction | DeleteTweetAction | RefreshTweetsAction;
export type {
TweetsAction,
AddTweetAction,
DeleteTweetAction,
RefreshTweetsAction,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment