리액트 구구단 게임 만들기

hhkim·2021년 7월 21일
0
post-thumbnail

웹 게임을 만들며 배우는 React에서 실습했던 내용을 토대로 다시 만들어보는 구구단 게임

🔗 react-gugudan 완성본


개발 환경 설정

CRA 없이 만들기 도전!

  • npm init: 노드 프로그램 시작. 패키지 관리를 위한 package.json 생성
    • project name, author, license만 작성
  • npm i react react-dom: react, react-dom 설치
  • npm i -D webpack webpack-cli: webpack, webpack-cli 개발 모드로 설치
  • npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader: 바벨 설치
    • @babel/core: 바벨 핵심
    • @babel/preset-env: 브라우저에 따른 지원
    • @babel/preset-react: 리액트 지원(jsx)
    • babel-loader: babel과 webpack 연결
  • npm i -D react-refresh @pmmmwh/react-refresh-webpack-plugin: 핫 리로딩을 위한 react-refresh 설치
  • npm i -D webpack-dev-server: 개발용 서버 설치
    • package.json에 scripts 추가
 "scripts": {
    "start": "webpack serve --env development"
  },

화면 로직과 직접적으로 상관이 있는 react 관련 라이브러리는 배포용 dependencies으로, 그렇지 않은 라이브러리는 개발용 devDependencies로 설치

  • 개발용 라이브러리는 빌드 후 코드에 포함되지 않는다.

webpack.config.js

entry - module - plugins - output

const RefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

module.exports = {
  mode: 'development',
  devtool: 'eval',
  resolve: {
    extensions: ['.js', '.jsx'],
  },

  entry: {
    app: ['./index'],
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',	// use를 쓰면 options 못 씀 (babel.config.js 파일 생성해야 함)
        options: {
          presets: ['@babel/preset-env', '@babel/preset-react'],
        },
      },
    ],
  },
  plugins: [new RefreshWebpackPlugin()],
  output: {
    filename: 'bundle.js',
    publicPath: '/',
  },
  devServer: {
    publicPath: '/',
    hot: true,
  },
};

requireimport의 차이

참고

  • require는 NodeJS에서 쓰는 CommonJS이고, import는 ES6 키워드
  • module.exportsexport도 같은 차이
  • import로 특정 멤버만 가져올 수 있어서 효율적이다.
    예) import { moduleFunc, moduleFunc2 } from module;

코드 작성

Gugudan.js

  • 훅스를 배워서 적용해보았다.
    확실히 클래스 기반 컴포넌트를 작성할 때보다 코드가 줄고 알아보기도 편하다.
  • componentDidMount()를 쓰고 싶어서 찾아보니 Hooks에서는 useEffect()를 써야 한단다. (참고)
import React, { useState, useRef, useEffect } from 'react';
import './Gugudan.css';

const Gugudan = () => {
  const [first, setFirst] = useState(Math.ceil(Math.random() * 9));
  const [second, setSecond] = useState(Math.ceil(Math.random() * 9));
  const [value, setValue] = useState('');
  const [result, setResult] = useState('🙄');
  const [score, setScore] = useState(0);
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  });

  const onFormSubmit = (event) => {
    event.preventDefault();
    if (parseInt(value) === first * second) {
      setResult('😊');
      setFirst(Math.ceil(Math.random() * 9));
      setSecond(Math.ceil(Math.random() * 9));
      setValue('');
      setScore(score + 1);
    } else {
      setResult('🤔');
      setValue('');
      setScore(score - 1);
    }
  };

  const onInputChange = (event) => {
    setValue(event.target.value);
  };

  return (
    <div className="gugudan">
      <div className="score">Score: {score}</div>
      <form onSubmit={onFormSubmit} className="gugudan-form">
        <span className="question">
          {first} x {second} ={' '}
        </span>
        <input
          type="number"
          ref={inputRef}
          value={value}
          onChange={onInputChange}
          className="answer"
          required
        ></input>
      </form>
      <div className="result">{result}</div>
    </div>
  );
};

export default Gugudan;

webpack CSS 설정

참고

  • npm i -D css-loader style-loader
    • css-loader: webpack과 css 연결
    • style-loader: html head에 style 태그 삽입
  • webpack.config.js에 rules 추가
{
  test: /\.css$/,
  use: ['style-loader', 'css-loader'],	// 오른쪽부터 실행
},

0개의 댓글