1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vite × React × TypeScript】Chakra UI v3でボタンのローディング切り替えの実装方法

Last updated at Posted at 2024-12-09

はじめに

お疲れ様です。りつです。

現在以下のUdemyの講座を学習中です。

今回は、Chakra UI v3のボタンに関するtipsをご紹介します。

問題

参考動画の中では、ボタンの実装を以下のように行っていました。

isLoading属性を指定することで、ボタンのローディングのON/OFFを切り替えられるとのことでしたが、こちらの動画では@chakra-ui/react": "1.2.1が使用されていたため、Chakra UIのv3ではうまく動きませんでした。

src/components/atoms/button/PrimaryButton.tsx
import { Button } from "@chakra-ui/react";

/** 省略 **/

<Button
  bg="teal.400"
  color="white"
  _hover={{ opacity: 0.8 }}
  disabled={disabled}
  isLoading={loading}
  onClick={onClick}>
    { children }
</Button>

/** 省略 **/

解決方法

解決にあたって、注意する点が2点あります。

  1. Buttonのインポートは@chakra-ui/reactではなく、@/components/ui/buttonから行う
  2. isLoading属性ではなく、loading属性を使用する

1. Buttonのインポートは@chakra-ui/reactではなく、@/components/ui/buttonから行う

まず1つ目の注意点ですが、Buttonコンポーネントのインポート元が@chakra-ui/reactの場合、後述するloading属性が使えません。

公式サイトの以下のページを元にChakra UI v3のインストールを行った場合、src/components/uiディレクトリ配下にbutton.tsxというファイルが自動生成されているはずですので、そちらからButtonコンポーネントをインポートするようにしましょう。

もしsrc/components/ui/button.tsxが存在しない場合は、以下のコマンドを実行してください。

npx @chakra-ui/cli snippet add button

インポート元を修正した場合、ソースコードは以下のようになります。

src/components/atoms/button/PrimaryButton.tsx
import { Button } from "@/components/ui/button";

/** 省略 **/

<Button
  bg="teal.400"
  color="white"
  _hover={{ opacity: 0.8 }}
  disabled={disabled}
  isLoading={loading}
  onClick={onClick}>
    { children }
</Button>

/** 省略 **/

自分の場合は上記のインストール手順だけではエラーになってしまったため、追加で以下の記事の内容を実施しています。
同じエラーが発生する場合は参考にしてみてください。

2. isLoading属性ではなく、loading属性を使用する

Chakra UI v3の公式ドキュメントによると、ローディング中のボタンを表現するには、loading属性を追加してあげればよいとのことです。

Use the loading and loadingText prop to show a loading spinner

試しにloading属性を付与すると、画面上はボタンがローディング状態になります。

src/components/atoms/button/PrimaryButton.tsx
import { Button } from "@/components/ui/button";

/** 省略 **/

<Button
  bg="teal.400"
  color="white"
  _hover={{ opacity: 0.8 }}
  disabled={disabled}
  loading
  onClick={onClick}>
    { children }
</Button>

/** 省略 **/

image.png

ここで、例えばbooleanで定義されたloadingという変数の値によって、ボタンのローディング状態を切り替えたい場合、以下のように記述できます。

src/components/atoms/button/PrimaryButton.tsx
import React, { memo } from "react";
import { Button } from "@/components/ui/button"

type Props = {
  children: React.ReactNode;
  disabled?: boolean;
  loading?: boolean;
  onClick: () => void;
}

export const PrimaryButton: React.FC<Props> = memo((props) => {
  const { children, disabled = false, loading = false, onClick } = props;
  return (
    <Button
      bg="teal.400"
      color="white"
      _hover={{ opacity: 0.8 }}
      disabled={disabled}
      loading={loading}
      onClick={onClick}>
        { children }
    </Button>
  );
});
上記ボタンの呼び出し元(疑似ログイン機能)
src/components/pages/Login.tsx
import React, { memo, useState } from "react";
import { Box, Flex, Heading, Input, Separator, Stack } from "@chakra-ui/react";
import { PrimaryButton } from "../atoms/button/PrimaryButton";
import { useAuth } from "@/hooks/useAuth";

export const Login: React.FC = memo(() => {
  const { login, loading } = useAuth();
  const [userId, setUserId] = useState('');

  const onChangeUserId = (e: React.ChangeEvent<HTMLInputElement>) => setUserId(e.target.value);

  const onClickLogin = () => login(userId);

  return (
    <Flex align="center" justify="center" height="100vh">
      <Box bg="white" w="sm" p={4} borderRadius="md" shadow="md">
        <Heading as="h1" size="lg" textAlign="center">ユーザー管理アプリ</Heading>
        <Separator my={4} />
        <Stack gap={6} py={4} px={10}>
          <Input placeholder="ユーザーID" value={userId} onChange={onChangeUserId}/>
          <PrimaryButton
            disabled={userId === ''}
            loading={loading}
            onClick={onClickLogin}
          >
            ログイン
          </PrimaryButton>
        </Stack>
      </Box>
    </Flex>
  );
});

上記により、ログイン中はログインボタンをローディング中にし、ログイン成功後はローディングを解除する、といった挙動が実現できます。

おわりに

自分は最初、Buttonコンポーネントを@chakra-ui/reactからインポートしていたため、公式ドキュメントに記載されているはずのloading属性がエラーとなってしまったので、少し困惑しました。

ボタンのローディング切り替えは便利な機能なので、今後の個人開発などでも活用していければと思います。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?