ツクログ

tsukulognet

tsukulognet

道産子。Reactでなまら面白いものを作りたい。

【React】ボタンを作る

eye catch

開発環境の構築

Reactアプリの開発環境の構築についてはReactの開発環境を構築するをご覧ください。

ディレクトリ構成

プロジェクトのディレクトリ構成を下記のようにします。「my-app」はプロジェクト名です。

my-app
 └── src
     ├── components
     │   └── Button.js
     ├── App.css
     ├── App.js
     ├── index.css
     └── index.js

styled-componentsのインストール

ターミナルで以下のコマンドを実行してstyled-componentsをインストールします。

yarn add styled-components

Buttonコンポーネントを作成する

Reactでは、コンポーネントと呼ばれる部品を組み合わせてUIを構築します。

コンポーネントはpropsと呼ばれるパラメータを受け取り、表示するビューの階層構造を返します。

ということで、src/components配下に以下のコンポーネントを作成します。

Button

ボタン要素を返すButtonコンポーネントをstyled-componentsで作成します。

components/Button.js

import React from 'react'
import styled from 'styled-components'

const Button = styled.button`
    background-color: ${({ theme }) => (theme && theme.background) || "lightgray"};
    border: none;
    border-radius: 0.6vmin;
    cursor: ${({ isDisabled }) => (isDisabled ? "cursor" : "pointer")};
    color: ${({ theme }) => (theme && theme.color) || "#333333"};
    font-size: ${({ size }) => (size && size.fontSize) || "1em"};
    outline: none;
    opacity: ${({ isDisabled }) => (isDisabled ? 0.5 : 1)};
    padding: ${({ size }) => (size && size.fontSize) || "1em 2em"};
    pointer-events: ${({ isDisabled }) => (isDisabled ? "none" : "auto")};
    user-select: none;
`;

export default Button

このコンポーネントはpropsとして4つの値(theme、size、isDisabled、onClick)を受け取ります。

4つの値については次の通りです。

theme

backgroundとcolorのプロパティを持つオブジェクトであり、値はいずれもカラーコードまたはカラー名を文字列で指定します。

<Button
  theme={{
    background: '#aaaaaa',
    color: 'white'
  }}
>

受け取った値は、以下のようにしてcssのbackground-colorプロパティとcolorプロパティにセットされ、これによりボタンのテーマが設定されます。

background-color: ${({ theme }) => (theme && theme.background) || BUTTON_THEMES.default.background};
color: ${({ theme }) => (theme && theme.color) || BUTTON_THEMES.default.color};

尚、themeを受け取らなかった場合は、それぞれデフォルトのカラーが設定されます。

size

fontSizeとpaddingのプロパティを持つオブジェクトであり、fontSizeプロパティにはフォントサイズを、paddingプロパティには上下左右のパディングをいずれも文字列で以下のように指定します。

<Button
  size={{
     fontSize: '1em',
     padding: '10px 20px'
  }}
>

受け取った値は、以下のようにしてcssのfont-sizeプロパティとpaddingプロパティにセットされ、これによりボタンのテーマが設定されます。

font-size: ${({ size }) => (size && size.fontSize) || BUTTON_SIZES.md.fontSize};
padding: ${({ size }) => (size && size.fontSize) || BUTTON_SIZES.md.padding};

尚、themeを受け取らなかった場合は、それぞれデフォルトのフォントサイズとパディングが設定されます。

isDisabled

ボタンのクリックが有効または無効の状態を示す真偽値であり、falseであればボタンのクリックが有効になり、trueであれば無効になります。

受け取った値は、以下のようにしてcssのcursor、opacity、pointer-eventsプロパティの値が設定される際の条件式で使われます。

cursor: ${({ isDisabled }) => (isDisabled ? "cursor" : "pointer")};
opacity: ${({ isDisabled }) => (isDisabled ? 0.5 : 1)};
pointer-events: ${({ isDisabled }) => (isDisabled ? "none" : "auto")};

isDisabledがtrueであればcssは

cursor: default;
opacity: .5;
pointer-events: none;

となり、ボタンのクリックは無効になります。

反対にfalseであればcssは、

cursor: pointer;
opacity: 1;
pointer-events: auto;

となり、ボタンのクリックが有効になります。

onClick

クリックされたときに実行する関数であり、関数名か無名関数で以下のように指定します。

// 関数名の場合
<Button
  onClick={handleClick}
>

// 無名関数の場合
<Button
  onClick={() => handleClick()}
>

受け取った値はbutton要素のonclick属性に設定されます。

Buttonコンポーネントの使いかた

Buttonコンポーネントは以下のようにして使用します。以下の例ではButtonコンポーネントはCount upボタンとして使われています。

App.js

import React from 'react'
import './App.css'

import Button from './components/Button'

const App = () => {
    const [count, setCount] = useState(0);
    const countUp = useCallback(() => setCount((p) => p + 1), []);
    const buttonTheme = {
        background: "orange",
        color: "#ffffff"
    };

    const style = {
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        height: "100vh",
        justifyContent: "center"
    };

    return (
        <div style={style}>
            <div>count: {count}</div>
            <Button onClick={countUp} theme={buttonTheme}>
                Count up
            </Button>
        </div>
    );
};

export default App

App.jsを上書きするとブラウザがリロードされてCount upボタンと現在のカウント数が表示されます。Count upボタンをクリックすると現在のカウント数が1ずつカウントアップされます。

Demo

下記で実際の動作を確認できます。