实践React应用百日挑战〜05 计算器〜

首先

这篇文章是与@Sicut_study合作的【React应用100课题】系列文章配合,用于输出的文章。

    • 実装ルールや成果物の達成条件は元記事に従うものとします。

 

    元記事との差別点として、具体的に自分がどんな実装を行ったのか(と必要に応じて解説)を記載します。

我打算跟随Sicut_study的100个敲门,并在100天内学会React。

这篇原文在这里。

 

之前的文章

 

请问有什么疑问吗?

制作一个简易的计算器

规则 (guī zé)

从原始文章中引用

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

 

    • TypeScriptを利用する

 

    要件をみたせばデザインなどは自由

达成条件

从原始文章中引用

    • 四則演算(加算、減算、乗算、除算)が正確に行えること。

 

    • 数字と演算子の入力が可能で、計算結果が表示されること。

 

    • クリアボタンで入力と結果をリセットできること。

 

    連続した数字入力など計算ができないときはエラーを表示する

执行

本文将按照以下方针进行实施。

    • ボタンをコンポーネント化する

 

    • 小数点の計算も可能とする

 

    計算機能の実装にはMath.jsを活用する

代码如下。

/** @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;
/** @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次。
如果你能支持我,我将非常高兴能得到你的关注。
我也期待着你的点赞和转发。

再见。

下一篇文章

 

广告
将在 10 秒后关闭
bannerAds