14
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Reactアプリ100本ノックを実践する 〜05 Calc〜

14
Last updated at Posted at 2023-11-16

はじめに

こちらの記事は、@Sicut_studyさんがアップしている【Reactアプリ100本ノック】シリーズに相乗りし、アウトプットを行うための記事になります。

  • 実装ルールや成果物の達成条件は元記事に従うものとします。
  • 元記事との差別点として、具体的に自分がどんな実装を行ったのか(と必要に応じて解説)を記載します。

@Sicut_studyさんのノック100本についていき、Reactを100日間学ぶのが目標です。

今回の元記事はこちら

前回の記事

問題

簡易的な電卓を作成する

ルール

元記事より引用

  • 主要なライブラリやフレームワークはReactである必要がありますが、その他のツールやライブラリ(例: Redux, Next.js, Styled Componentsなど)を組み合わせて使用することは自由
  • TypeScriptを利用する
  • 要件をみたせばデザインなどは自由

達成条件

元記事より引用

  • 四則演算(加算、減算、乗算、除算)が正確に行えること。
  • 数字と演算子の入力が可能で、計算結果が表示されること。
  • クリアボタンで入力と結果をリセットできること。
  • 連続した数字入力など計算ができないときはエラーを表示する

実装

本記事では以下の方針で実装していきます。

  • ボタンをコンポーネント化する
  • 小数点の計算も可能とする
  • 計算機能の実装にはMath.jsを活用する

コードは以下のようになりました。

src/components/Button.tsx
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";

const buttonStyle = css`
  flex: 1;
  padding: 15px;
  margin: 5px;
  font-size: 18px;
  border-radius: 8px;
  background-color: #61dafb;
  color: #282c34;
  border: none;
  cursor: pointer;
  &:hover {
    background-color: #51cfeb;
  }
`;

interface ButtonProps {
  onClick: React.MouseEventHandler<HTMLButtonElement>;
  children: React.ReactNode;
}

const Button = ({ onClick, children }: ButtonProps) => (
  <button css={buttonStyle} onClick={onClick}>
    {children}
  </button>
);

export default Button;
src/App.tsx
/** @jsxImportSource @emotion/react */
import { useState } from "react";
import { css } from "@emotion/react";
import { evaluate } from "mathjs";
import Button from "./components/Button";

const containerStyle = css`
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #282c34;
  min-height: 100vh;
  color: white;
  font-family: 'Arial', sans-serif;
`;

const screenStyle = css`
  width: 300px;
  background: #fff;
  color: #333;
  margin-top: 10px;
  margin-bottom: 10px;
  text-align: right;
  padding: 20px;
  font-size: 24px;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
`;

const buttonRowStyle = css`
  display: flex;
  justify-content: space-between;
  width: 300px;
`;

const App = () => {
  const [input, setInput] = useState("");
  const [result, setResult] = useState("");

  const handleButtonClick = (val: string) => {
    setInput((prev) => prev + val);
  };

  const calculateResult = () => {
    try {
      const result = evaluate(input);
      setInput(result.toString());
      setResult("");
    } catch (error) {
      setResult("Error");
      setInput("");
    }
  };

  const clearInput = () => {
    setInput("");
    setResult("");
  };

  return (
    <div css={containerStyle}>
      <div css={screenStyle}>{input || "0"}</div>
      <div css={buttonRowStyle}>
        <Button onClick={() => handleButtonClick("1")}>1</Button>
        <Button onClick={() => handleButtonClick("2")}>2</Button>
        <Button onClick={() => handleButtonClick("3")}>3</Button>
        <Button onClick={() => handleButtonClick("+")}>+</Button>
      </div>
      <div css={buttonRowStyle}>
        <Button onClick={() => handleButtonClick("4")}>4</Button>
        <Button onClick={() => handleButtonClick("5")}>5</Button>
        <Button onClick={() => handleButtonClick("6")}>6</Button>
        <Button onClick={() => handleButtonClick("-")}>-</Button>
      </div>
      <div css={buttonRowStyle}>
        <Button onClick={() => handleButtonClick("7")}>7</Button>
        <Button onClick={() => handleButtonClick("8")}>8</Button>
        <Button onClick={() => handleButtonClick("9")}>9</Button>
        <Button onClick={() => handleButtonClick("*")}>*</Button>
      </div>
      <div css={buttonRowStyle}>
        <Button onClick={clearInput}>C</Button>
        <Button onClick={() => handleButtonClick("0")}>0</Button>
        <Button onClick={() => handleButtonClick(".")}>.</Button>
        <Button onClick={() => handleButtonClick("/")}>/</Button>
      </div>
      <div css={buttonRowStyle}>
        <Button onClick={calculateResult}>=</Button>
      </div>
    </div>
  );
};

export default App;

完成

完成形はこのようになりました。

image.png

image.png

最後に

まだまだ先は長いですが、100回完走を目指して継続していきます。
応援してくれる方はぜひフォローいただけると嬉しいです。
いいね、ストックもお待ちしております。

ではまた。

次回の記事

14
19
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
14
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?