Skip to content

Slackクローン 6. Userボタン

公開日

表紙

6. Userボタン

サインアップの修正

サインアップ処理でユーザ名が取れていないので、その修正を実施。

Convexのパスワードドキュメントに従う

Convex Auth
Authentication library for your Convex backend
Convex Auth favicon https://labs.convex.dev/auth/config/passwords#customize-user-information

convexAuthのプロバイダにカスタムパスワードを追加することで実現する。

convex/auth.ts
import GitHub from "@auth/core/providers/github";
import Google from "@auth/core/providers/google";
import { Password } from "@convex-dev/auth/providers/Password";
import { convexAuth } from "@convex-dev/auth/server";
import { DataModel } from "./_generated/dataModel";
 
const CustomPassword = Password<DataModel>({
  profile(params) {
    return {
      email: params.email as string,
      name: params.name as string,
    };
  },
});
 
export const { auth, signIn, signOut, store } = convexAuth({
  providers: [CustomPassword, GitHub, Google],
});
 

これで名前が登録される。 GitHubとGoogleの認証はデフォルトで登録されている。

ユーザボタン作成

avatarとdropdown-menuを導入

terminal
$ bunx --bun shadcn@latest add avatar dropdown-menu

ユーザ取得処理

convex/users.ts
import { getAuthUserId } from "@convex-dev/auth/server";
import { query } from "./_generated/server";
 
export const current = query({
  args: {},
  handler: async (ctx) => {
    const userId = await getAuthUserId(ctx);
 
    if (userId === null) {
      return null;
    }
 
    return await ctx.db.get(userId);
  },
});
src/features/auth/hooks/use-current-user.ts
import { useQuery } from "convex/react";
import { api } from "../../../../convex/_generated/api";
 
export const useCurrentUser = () => {
  const data = useQuery(api.users.current);
  const isLoading = data === undefined;
 
  return { data, isLoading };
};
 

ログインアバター表示

src/features/auth/components/user-button.tsx
"use client";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useAuthActions } from "@convex-dev/auth/react";
import { Loader, LogOut } from "lucide-react";
import { useCurrentUser } from "../hooks/use-current-user";
 
export const UserButton = () => {
  const { signOut } = useAuthActions();
  const { data, isLoading } = useCurrentUser();
 
  if (isLoading) {
    return <Loader className="site-4 animate-spin text-muted-foreground" />;
  }
 
  if (!data) {
    return null;
  }
 
  const { image, name } = data;
 
  const avatarFallback = name!.charAt(0).toLocaleUpperCase();
 
  return (
    <DropdownMenu modal={false}>
      <DropdownMenuTrigger className="outline-none relative">
        <Avatar className="size-10 hover:opacity-75 transition">
          <AvatarImage alt={name} src={image} />
          <AvatarFallback className="bg-sky-500 text-white">
            {avatarFallback}
          </AvatarFallback>
        </Avatar>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="center" side="right" className="w-60">
        <DropdownMenuItem
          onClick={async () => {
            await signOut();
            location.reload();
          }}
          className="h-10"
        >
          <LogOut className="size-4 mr-2" /> Logout
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
};
 

[Tips] ログアウトでリロードされない

手順どおりやってサインアウトしてもリロードされない問題が発生。 見返しても間違いがないのでissueを覗くと、直近で同じエラーが起きている人がいた。 β板なのでまだ色々変わっているのでしょうがない。

Not auto redirect after execute signOut function · Issue #92 · get-convex/convex-auth
My project use: "@auth/core": "^0.35.3", "@convex-dev/auth": "^0.0.71", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "class-variance-a...
Not auto redirect after execute signOut function · Issue #92 · get-convex/convex-auth favicon https://github.com/get-convex/convex-auth/issues/92
Not auto redirect after execute signOut function · Issue #92 · get-convex/convex-auth

回避策として単純にログアウト後に手動でリロードすることだったので、 location.reload(); を追加して暫定対応