React入門 - 演習1 - 簡易計算画面を作ってみよう

# 完成イメージ

ここまでで学んだ知識を活かして
下記のようなプログラムを作ってみよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559029/f7ea90ea-d351-7af9-d977-4007a49ca62e.png)

useStateだけでなくuseContextやreduxを使ってみてもよいです。

# プロジェクト作成

以下のようにプロジェクトを作成し、`yarn start`でLearn React画面が表示されるこを確認してください。
※reduxを使用して作成しても構いません。その場合は、[Part4.2](https://qiita.com/yokowake12345/items/443776233190bb4cbaa1)を参考にプロジェクトを作成してください。

```
npx create-react-app プロジェクト名 --template typescript
cd プロジェクト名
yarn start 
```

# 参考ソース

後ほど公開します。

<!--

App.tsx

```typescript
import React, { useState } from "react";
import InputText from "./input-text";
import Buttons from "./buttons";

// 演算子型
export type CalcType = "+" | "-" | "*" | "/"; // https://chaika.hatenablog.com/entry/2020/08/16/083000

// 右辺or左辺
export type LeftOrRight = "left" | "right";

const App: React.FC = () => {
  // ステート
  const [calcType, setCalcType] = useState<CalcType>("+"); // 演算子
  const [calcResult, setCalcResult] = useState(""); // 計算結果
  const [rightVal, setRightVal] = useState(0); // 右辺
  const [leftVal, setLeftVal] = useState(0); // 左辺

  // 演算子変更イベント
  const handleCalcTypeClick = async (calcType: CalcType) => {
    await setCalcType(calcType);
    calc(undefined, calcType);
  };

  // 入力値変更
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    calc(e, calcType);
  };

  // 計算処理
  const calc = (
    e: React.ChangeEvent<HTMLInputElement> | undefined,
    calType: CalcType = calcType
  ) => {
    let left: number = leftVal;
    let right: number = rightVal;

    if (e) {
      if (e.target.name === "left") {
        left = Number(e.target.value);
        setLeftVal(left);
      }

      if (e.target.name === "right") {
        right = Number(e.target.value);
        setRightVal(right);
      }
    }

    if (calType === "+") setCalcResult((left + right).toString());
    if (calType === "-") setCalcResult((left - right).toString());
    if (calType === "*") setCalcResult((left * right).toString());
    if (calType === "/") setCalcResult((left / right).toString());
  };

  return (
    <>
      <Buttons
        onClick={(calcType: CalcType) => handleCalcTypeClick(calcType)}
      />
      <div>
        <InputText onChange={handleInputChange} leftOrRight={"left"} />
        {calcType}
        <InputText onChange={handleInputChange} leftOrRight={"right"} />
        {" = " + calcResult}
      </div>
    </>
  );
};

export default App;
```

button-calc-type.tsx

```typescript
import React from 'react';
import {CalcType} from './App';

const ButtonCalcType: React.FC<{calcType: CalcType, onClick: (calcType: CalcType) => void}> = ({calcType, onClick}) => {

  // ★★★ style={{margin: '6px'}}
  return (
    <button style={{margin: '6px'}} onClick={() => onClick(calcType)}>
      { calcType }
    </button>
  )
}

export default ButtonCalcType;
```

buttons.tsx

```typescript
import React from 'react';
import ButtonCalcType from './button-calc-type';
import {CalcType} from './App';

const Buttons: React.FC<{onClick: (calcType: CalcType) => void}> = ({onClick}) => {
  return (
    <>
      <ButtonCalcType onClick={onClick} calcType={'+'} />
      <ButtonCalcType onClick={onClick} calcType={'-'} />
      <ButtonCalcType onClick={onClick} calcType={'*'} />
      <ButtonCalcType onClick={onClick} calcType={'/'} />
    </>
  )
}

export default Buttons;
```

input-text.tsx

```typescript
import React from 'react';
import {LeftOrRight} from './App';

// ★★★ onChangeの渡し方はネットで調べた https://zenn.dev/nbr41to/articles/3f1ae8cbc532b6
const InputText: React.FC<{leftOrRight: LeftOrRight, onChange: (event: React.ChangeEvent<HTMLInputElement>) => void}> = ({leftOrRight, onChange}) => {

  return (
    <input type="text" style={{margin: '10px'}} onChange={(e) => onChange(e)} name={leftOrRight} />
  )
}

export default InputText;
```


-->