Follow機能: Front-end

次に、ユーザーをフォローするためのUIを作成していきましょう。 現在は、Global Timelineなどに表示されるユーザーのアイコンをクリックすると、そのユーザーのPost一覧を表示できるようになっています。 今回、この画面にフォローボタンを足していきます。

PostsBySpecifiedUser

./src/containers/PostsBySpecifiedUser.jsを編集していきます。

以下のPostsBySpecifiedUser.jsの中身をコピーし、./src/containers/PostsBySpecifiedUser.jsを置き換えてください。

主な変更点は以下です。

useEffect()でログイン中のユーザー情報を取得

useEffect(() => {
  //getPosts(INITIAL_QUERY); <-変更前

  //↓↓↓↓↓↓↓変更部分↓↓↓↓↓↓↓
  const init = async() => {
    const currentUser = await Auth.currentAuthenticatedUser();
    setCurrentUser(currentUser);

    setIsFollowing(await getIsFollowing({followeeId: userId, followerId: currentUser.username}));

    getPosts(INITIAL_QUERY);
  }
  init()
  //↑↑↑↑↑↑↑↑ここまで↑↑↑↑↑↑↑↑↑↑

  const subscription = API.graphql(graphqlOperation(onCreatePost)).subscribe({
    next: (msg) => {
      const post = msg.value.data.onCreatePost;
      if (post.owner !== userId) return;
      dispatch({ type: SUBSCRIPTION, post: post });
    }
  });
  return () => subscription.unsubscribe();
}, []);
  • useEffect()内で、Amplify AuthのAuth.currentAuthenticatedUserメソッドを呼び出し、現在のユーザー情報を取得しています。
  • getIsFollowing関数を呼び出し、ログイン中のユーザーとアプリ上で表示されているユーザーのフォロー関係を取得し、isFollowingステートに格納しています。

getIsFollowing()

const getIsFollowing = async ({followerId, followeeId}) => {
  const res = await API.graphql(graphqlOperation(getFollowRelationship,{
    followeeId: followeeId,
    followerId: followerId,
  }));
  console.log(res)
  return res.data.getFollowRelationship !== null
}
  • getFollowRelationship Queryを実行し、followerIdUsernameとするユーザーが、followeeIdUsernameとするユーザーをフォローしているか返す

フォローボタンのコンポーネントを追加

<PostList
  isLoading={isLoading}
  posts={posts}
  getAdditionalPosts={getAdditionalPosts}
  listHeaderTitle={userId}

  //↓↓↓↓↓↓↓追加部分↓↓↓↓↓↓↓
  listHeaderTitleButton={
    ( currentUser && userId !== currentUser.username ) &&
    ( isFollowing ? 
      <Button  variant='contained' color='primary' onClick={unfollow}>Following</Button> 
    :
      <Button variant='outlined' color='primary' onClick={follow}>Follow</Button> 
    )
  }
  //↑↑↑↑↑↑↑↑ここまで↑↑↑↑↑↑↑↑↑↑
/>
  • PostListコンポーネントを呼び出す際に、listHeaderTitleButtonでフォロー用のボタンを追加しています
  • 次の二つの条件で、フォローボタンを表示するか決めています
    • currentUser: 先ほどのinit関数が実行され、すでにcurrentUserがセットされているか
    • userId !== currentUser.username: 自分自身でないか
  • isFollowingを参照し、フォローしている場合とそうでない場合でフォローボタンの文言やみため、ボタンクリック時の挙動を切り替えています

フォロー・フォロー解除用関数

  const follow = async () => {
    const input = {
      followeeId: userId,
      followerId: currentUser.username,
      timestamp: Math.floor(Date.now() / 1000),
    }
    const res = await API.graphql(graphqlOperation(createFollowRelationship, {input: input}));

    if(!res.data.createFollowRelationship.erros) setIsFollowing(true);
  }

  const unfollow = async() => {
    const input = {
      followeeId: userId,
      followerId: currentUser.username,
    }
    const res = await API.graphql(graphqlOperation(deleteFollowRelationship,{input: input}));

    if(!res.data.deleteFollowRelationship.erros) setIsFollowing(false);
  }
  • follow
    • createFollowRelationship Mutationを実行し、新規FollowRelationshipを作成します
    • 現在のログインユーザーをfollowerId
    • PostsBySpecifiedUserコンポーネントで表示中のユーザーをfolloweeId
  • unfollow
    • deleteFollowRelationshipMutationを実行し、指定のFollowRelationshipを削除します

挙動の確認

  1. 実行していない場合は次のコマンドをそれぞれ別のターミナルウィンドウで実行します
amplify mock api
npm start
  1. 適当な他のユーザーのアイコンを押してユーザーのPost一覧に飛び、フォローボタンを押してみましょう。
  2. Amplify GraphQL ExplorerでlistFollowRelationshipを実行して、新しいアイテムが作成されていることを確認します
  3. ついでにFollowingボタンをクリックして、フォロー解除機能が動いていることも確認してみましょう

なぜ$ amplify pushしていないにも関わらず、schema.graphqlの変更が行われた後の挙動をGraphQL APIが行っているのでしょうか。 Amplify CLIでは、 $ amplify pushを実行すると、Amplify Framework(SDK)がリソースにアクセスするために必要なエンドポイント、IDといった情報をaws-exports.jsにexportします。 aws-exports.jsを使ってAmplifyの初期設定を行うと、リソース変更や追加をしても設定を書き換える必要がなくなり、非常に楽です。 そして$ amplify mockコマンドを使用してAmplify Mockingをしている間だけ、ローカルでたちあがったMock ServerのGraphQL Endpointを指すようにaws-exports.jsが書き換わります。