React 기본 학습 -3. webpack-dev-server 와 핫리로딩 - 끝말잇기 예제

React 기본 학습 -3. webpack-dev-server 와 핫리로딩 - 끝말잇기 예제

리액트 강좌를 보면서 학습한 내용 정리용.

리액트 무료 강좌(웹게임) - ZeroCho TV

webpack-dev-server 와 핫리로딩 - 끝말잇기 예제

핫리로딩에 필요한 패키지
  1. @pmmmwh/react-refresh-webpack-plugin
  2. react-refresh/babel
리로딩과 핫리로딩의 차이점

webpack.config.js

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

module.exports = {
    name: 'wordrelay-setting',
    mode: 'development', // 실서비스: production
    devtool: 'eval',
    resolve: {
        extensions: ['.js', '.jsx']
    },

    entry: {
        app: ['./client'],
    }, // 입력

    module: {
        rules: [{
            test: /\.jsx?/,
            loader: 'babel-loader',
            options: {
                presets: [
                    // preset 에 상세 옵션 줄때 아래와 같이 설정 가능
                    ['@babel/preset-env', {
                        targets: {
                            browsers: ['> 5% in KR'], // 한국에서 점유율 5% 이상 브라우저에 대응
                        },
                        debug: true,
                    }], '@babel/preset-react'], // plugin 들의 모음이 preset 임.
                plugins: [
                    '@babel/plugin-proposal-class-properties',
                    'react-refresh/babel'
                    ]
            },
        }],
    },
    plugins: [
        new webpack.LoaderOptionsPlugin({ debug: true }),
        new RefreshWebpackPlugin(),
    ], // 추가적으로 붙이고 싶은 것들이 있으면 여기

    output: {
        // path 와 publicPath 의 차이
        // path는 실제경로. publicPath 는 가상의 경로(상대경로)
        path: path.join(__dirname, 'dist'), // path.join 은 현재폴더 경로 + dist 를 반환함
        filename: 'app.js',
        publicPath: '/dist/', // publicPath 는 node의 express.static 과 비슷
    }, // 출력
    
    devServer: {
        publicPath: '/dist/',
        hot: true // 핫리로딩 - 변경점 감지
    },
};

package.json

{
  "name": "lecture",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack serve --env development"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.3",
    "@babel/plugin-proposal-class-properties": "^7.12.1",
    "@babel/preset-env": "^7.12.1",
    "@babel/preset-react": "^7.12.5",
    "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
    "babel-loader": "^8.2.1",
    "react-refresh": "^0.9.0",
    "webpack": "^5.4.0",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0"
  }
}

client.jsx

const React = require('react'); // require는 node의 모듈 시스템
const ReactDom = require('react-dom');

const WordRelay = require('./WordRelay');

ReactDom.render(<div><WordRelay/></div>, document.querySelector('#root'));

WordRelay.jsx (Class 로 기입한 경우)

const React = require('react');
const { Component } = require('react');

class WordRelay extends Component {
  state = {
    word: '마이티',
    value: '',
    result: '',
  }

  onSubmitForm = (e) => {
    e.preventDefault();
    if(this.state.word[this.state.word.length -1] === this.state.value[0]){
      this.setState({
        result: '딩동댕',
        word: this.state.value,
        value: '',
      });
      this.input.focus();
    } else {
      this.setState({
        result: '',
        value: '',
      });
      this.input.focus();
    }
  };

  onChangeInput = (e) => {
    this.setState({ value: e.currentTarget.value });

  };

  input;

  onRefInput = (c) => {
    this.input = c;
  };

  render() {
    return (
      <>
        <div>{this.state.word}</div>
        <form onSubmit={this.onSubmitForm}>
          <input ref={this.onRefInput} value={this.state.value} onChange={this.onChangeInput} />
          <button>입력!!!!</button>
        </form>
        <div>{this.state.result}</div>
      </>);
  }

}
module.exports = WordRelay;

WordRelay.jsx (Hooks 로 기입한 경우)

const React = require('react');
const { useState, useRef } = React; 
// 이와같이 const { xxx } = React; 이런건 구조분해 문법이라 불림.
// exports 되는게 객체나 배열이면 구조 분해할 수 있음.

const WordRelay = () => {
  const [word, setWord] = useState('마이티');
  const [value, setValue] = useState('');
  const [result, setResult] = useState('');
  const inputRef = useRef(null);

  // Class 메소드들은 hooks 로 기입할 경우 더이상 클래스가 아니기때문에 따로 변수로 선언해 주어야 함.
  // hooks에서는 ref 에서는 항상 current 를 붙여줘야 함. (예) inputRef.current.focus(); )
  const onSubmitForm = (e) => {
    e.preventDefault();
    if(word[word.length -1] === value[0]){
      setResult('딩동댕');
      setWord(value);
      setValue('');
      inputRef.current.focus();
    } else {
      setResult('');
      setValue('');
      inputRef.current.focus();
    }
  };

  const onChangeInput = (e) => {
    setValue(e.currentTarget.value);
  };

  // hooks는 render 없이 바로 리턴
  // hooks 를 쓰게 되면 더이상 this 를 사용하지 않음(예) this.state.value)
  return (
    <>
      <div>{word}</div>
      <form onSubmit={onSubmitForm}>
        <input ref={inputRef} value={value} onChange={onChangeInput} />
        <button>입력!!!!</button>
      </form>
      <div>{result}</div>
    </>);
}
module.exports = WordRelay;

GitHub : React-Study-1/2.끝말잇기/

Pie's Tech Note

생계형 개발자의 메모장

comments powered by Disqus

    rss facebook twitter github youtube mail spotify instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora