Newer
Older
skillcheck-react / app / work / 01 / index.tsx
import { useRef, useState } from "react";
import { type Counter, createCounter } from "./counter";
import "./style.css"

const WAIT_SECONDS = 7;

/**
 * 7秒後に1億円もらえるボタン
 *
 * TODO: このプログラムには致命的なバグがある。それを修正し、正しく動作させること。
 */
export default function App() {
  const [wallet, setWallet] = useState(100000000);
  const [passedCount, setPassedCount] = useState(0);

  const counterRef = useRef<Counter | null>(null);

  const reset = () => {
    setWallet(100000000);
    setPassedCount(0);
  };

  const handleClickGet1Billion = () => {
    const newCounter = createCounter(WAIT_SECONDS, (_passed: number, left: number) =>
      setPassedCount(left)
    );

    if (counterRef.current) {
      counterRef.current.stop();
    }
    counterRef.current = newCounter;

    const 財布に1億円追加する関数 = () => {
      setWallet(wallet + 100000000);
    };

    const fn = async () => {
      await newCounter.promise; // 7秒待つ
      財布に1億円追加する関数();
    }

    fn();
  };

  return (
    <div className="App">

      <div className="box text-center">

        <h2>useStateを知る</h2>
        <h1>{`${WAIT_SECONDS}秒後に1億円もらえるボタン`}</h1>

        <p>
          <span>財布の中身: </span>
          <span
            style={{
              fontSize: "1.4em",
              fontStyle: "italic",
              ...(wallet < 0 && { color: "#e00" }),
            }}
          >
            &yen;
            {wallet.toLocaleString()}
          </span>
        </p>

        <p>
          {passedCount > 0 && (
            <span style={{ color: "#e00" }}>
              {passedCount}秒後に1億円ゲット!!!
            </span>
          )}
        </p>

        <button className="golden button-rich" onClick={handleClickGet1Billion}>
          {`${WAIT_SECONDS}秒後に1億円もらえるボタン`}
        </button>
      </div>

      <div
        className="box"
        style={{
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          gap: "8px",
        }}
      >
        <span>この世の欲望</span>

        <button
          className="silver button-rich"
          onClick={() => setWallet(wallet - 10000000)}
        >
          シャンパンタワー (&yen;10,000,000)
        </button>

        <button
          className="silver button-rich"
          onClick={() => setWallet(wallet - 40000000)}
        >
          マンション購入 (&yen;40,000,000)
        </button>

        <button
          className="silver button-rich"
          onClick={() => setWallet(wallet - 50000)}
        >
          上限赤スパ (&yen;50,000)
        </button>

        <div className="box">
          <button onClick={reset}>リセット</button>
        </div>
      </div>


      <div className="text-center bordered">
        <p className="text-center">
          <button className="golden button-rich">
            {`${WAIT_SECONDS}秒後に1億円もらえるボタン`}
          </button>
          &nbsp;を押すと、{WAIT_SECONDS}秒後に1億円が財布に追加されます。<br />
          それまでに、豪遊の限りを尽くして、財布の中身を減らしてみましょう。<br />
          するとあなたは、このプログラムには致命的なバグがあることに気づくでしょう。
        </p>
        <p>
          あなたはこのバグを修正し、このプログラムを正しく動作させることができますか?
        </p>
        <p>
          また、なにがバグの原因だったのか、言語化してみましょう。
        </p>
      </div>

    </div>
  );
}