MUIのButtonコンポーネントをラップした「自作Buttonコンポーネント」を作ってみた
概要
React ビギナーが MUI の Button コンポーネントをラップした自作の Button コンポーネントを作ってみました。
いろいろ詰まったところや不明点があり、またいつか実装する際にも同じところで詰まりそうなのでまとめておきます。
環境
react@18.2.0
react-router-dom@6.13.0
mui/material@5.13.5
コード
import { Button as MuiButton, ButtonProps as MuiButtonProps } from '@mui/material';
import { SxProps, Theme } from '@mui/material/styles';
import { LinkProps } from 'react-router-dom';
type ButtonType = {
component?: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
to?: string;
sx?: SxProps<Theme>;
} & MuiButtonProps;
export const Button = (props: ButtonType) => {
const { children, sx = [], ...buttonProps } = props;
return (
<>
<MuiButton
sx={[{ height: '50px', borderRadius: '5px' }, ...(Array.isArray(sx) ? sx : [sx])]}
{...buttonProps}
>
{children}
</MuiButton>
</>
);
};
<Button variant="outlined" size="large" component={Link} to="/link">
戻る
</Button>
ポイント
Property 'component' does not exist on type ...
調査
単純に MUI コンポーネントをラップした場合、こちらのエラーが発生すると思います。
解消には以下が参考になりました。
To be able to use the component prop, the type of the props should be used with type arguments. Just use React.ElementType as mentioned in the docs.
自作のコンポーネントでは component prop を定義する必要があるようです。
また、MUI の マニュアルに component prop について以下の記載がありました。
The component used for the root node. Either a string to use a HTML element or a component.
MUI のコンポーネントを直接呼び出す場合は component prop を指定できるが、ラップすると不可ということ?
root node とかが絡んでくるのかな・・・?後でつよい人に質問してみたい
解消
実際に定義したのは以下です。
import { Button as MuiButton, ButtonProps as MuiButtonProps } from '@mui/material';
type ButtonType = {
component?: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
to?: string;
} & MuiButtonProps;
- component と to プロパティを追加
- MUI Button コンポーネントの props を import して型を結合
がポイントになります。
sx プロパティのデフォルト値を設定し上書き可能にする
基本となる Button コンポーネントは高さなどを統一し、sx プロパティでマージンなどを適宜指定したいと思いました。
調査
参考になったのはこちらの公式ページ
ほぼそのまま使いましたが問題なく動作しました。
import {
Button as MuiButton,
ButtonProps as MuiButtonProps,
} from "@mui/material";
import { SxProps, Theme } from "@mui/material/styles";
import { LinkProps } from "react-router-dom";
type ButtonType = {
component?: React.ForwardRefExoticComponent<
LinkProps & React.RefAttributes<HTMLAnchorElement>
>;
to?: string;
sx?: SxProps<Theme>; //追加
} & MuiButtonProps;
export const Button = (props: ButtonType) => {
const { children, sx = [], ...buttonProps } = props; //追加
return (
<>
<MuiButton
sx={[
{ height: "50px", borderRadius: "5px" },
...(Array.isArray(sx) ? sx : [sx]), //追加
]}
{...buttonProps}
>
{children}
</MuiButton>
</>
);
};
初期値で定義した height 50px は sx プロパティで上書きすることが可能となりました。
※props の渡し方はこちらの記事が参考になりました。
まとめ
調べつつ何とか動くコンポーネントを作ることができました。
不明点については後ほど確認したいです。
Discussion