15
18

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本ノックを実践する 〜02 Counter〜

Last updated at Posted at 2023-11-07

はじめに

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

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

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

今回の元記事はこちら

前回の記事

問題

カウンターを作成する

ルール

元記事より引用

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

達成条件

元記事より引用

  1. 表示領域: 数字を表示するエリアが存在する。
  2. インクリメントボタン: このボタンをクリックすると、表示されている数字が 1 増える。
  3. デクリメントボタン: このボタンをクリックすると、表示されている数字が 1 減る。
  4. 初期表示: アプリを起動した際の数字は 0 である。
  5. ステート管理: React の useState や useReducer を使って、カウントの数字を管理する。

実装

前回のアプリをそのまま編集し、App.tsxに実装していきます。

useStateを使う場合

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

const App = () => {
  // カウンターの状態を宣言
  const [count, setCount] = useState(0);

  const counterStyle = css`
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    height: 100vh;
    text-align: center;
    background-color: #282c34;
    color: white;
    font-size: 2rem;
  `;

  const buttonStyle = css`
    padding: 10px 20px;
    margin: 5px;
    font-size: 1rem;
    cursor: pointer;
  `;

  return (
    <div css={counterStyle}>
      <p>{count}</p>
      <button css={buttonStyle} onClick={() => setCount(count + 1)}>
        インクリメント
      </button>
      <button css={buttonStyle} onClick={() => setCount(count - 1)}>
        デクリメント
      </button>
    </div>
  );
};

export default App;

useReducerを使う場合

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

// Stateの型を定義
type State = {
  count: number;
};

// Actionの型を定義
type Action = { type: "increment" } | { type: "decrement" };

// 初期状態
const initialState: State = { count: 0 };

// リデューサー関数
function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

const App = () => {
  // カウンターの状態を宣言
  const [state, dispatch] = useReducer(reducer, initialState);

  const counterStyle = css`
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    height: 100vh;
    text-align: center;
    background-color: #282c34;
    color: white;
    font-size: 2rem;
  `;

  const buttonStyle = css`
    padding: 10px 20px;
    margin: 5px;
    font-size: 1rem;
    cursor: pointer;
  `;

  return (
    <div css={counterStyle}>
      <p>{state.count}</p>
      <button css={buttonStyle} onClick={() => dispatch({ type: "increment" })}>
        インクリメント
      </button>
      <button css={buttonStyle} onClick={() => dispatch({ type: "decrement" })}>
        デクリメント
      </button>
    </div>
  );
};

export default App;

完成

デザインはまだまだ改善の余地がありますが、要件を満たしているのでこちらで完成。
カウントはきちんと機能します。

image.png

最後に

Reactアプリ100本ノックを100回分完走するつもりです。
応援してくれる方はぜひフォローいただけると嬉しいです。
いいね、ストックもお待ちしております。

ではまた。

次回の記事

15
18
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
15
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?