はじめに
お疲れ様です。りつです。
現在以下のUdemyの講座を学習中です。
今回は、Chakra UI v3のボタンに関するtipsをご紹介します。
問題
参考動画の中では、ボタンの実装を以下のように行っていました。
isLoading
属性を指定することで、ボタンのローディングのON/OFFを切り替えられるとのことでしたが、こちらの動画では@chakra-ui/react": "1.2.1
が使用されていたため、Chakra UIのv3ではうまく動きませんでした。
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点あります。
-
Button
のインポートは@chakra-ui/react
ではなく、@/components/ui/button
から行う -
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
インポート元を修正した場合、ソースコードは以下のようになります。
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
andloadingText
prop to show a loading spinner
試しにloading
属性を付与すると、画面上はボタンがローディング状態になります。
import { Button } from "@/components/ui/button";
/** 省略 **/
<Button
bg="teal.400"
color="white"
_hover={{ opacity: 0.8 }}
disabled={disabled}
loading
onClick={onClick}>
{ children }
</Button>
/** 省略 **/
ここで、例えばbooleanで定義されたloading
という変数の値によって、ボタンのローディング状態を切り替えたい場合、以下のように記述できます。
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>
);
});
上記ボタンの呼び出し元(疑似ログイン機能)
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
属性がエラーとなってしまったので、少し困惑しました。
ボタンのローディング切り替えは便利な機能なので、今後の個人開発などでも活用していければと思います。
参考