React - 구구단 (2), 끝말잇기

박종휘·2022년 12월 21일
0

React

목록 보기
5/5
post-thumbnail

구구단

1. React Hooks

  • Hooks : 함수 컴포넌트에 state와 ref 기능을 추가해준 것
index2.html

<html>
<head>
    <meta charset="UTF-8" />
    <title>구구단</title>
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과: <div id="root"><button>Like</button></div> -->
<script type="text/babel">
    // class GuGuDan extedns React.Component {
    //
    // }

    // Hooks : GuGuDan이라는 함수 컴포넌트에 state와 ref기능을 추가해준 것
    const GuGuDan = () => { // 함수 컴포넌트
        const [first, setFirst] = React.useState(Math.ceil(Math.random() * 9 /*초기값*/));
        // 구조 분해 문법 : 변수 자리에다가 배열쓰고 객체쓰고 하는 것 (= 비구조화 할당)
        const [second, setSecond] = React.useState(Math.ceil(Math.random() * 9));
        const [value, setValue] = React.useState('');
        const [result, setResult] = React.useState('');
        const inputRef = React.useRef(null);
        // use로 시작되는 것이 Hooks

         const onSubmitForm = (e) => {
            e.preventDefault();
            if (parseInt(value) === first * second) {
                setResult('정답: ' + value);
                setFirst(Math.ceil(Math.random() * 9));
                setSecond(Math.ceil(Math.random() * 9));
                setValue('');
                inputRef.current.focus();
            } else {
                setResult('땡');
                setValue('');
                inputRef.current.focus();
            }
        }

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

        return (
            <React.Fragment>
                <div>{first} 곱하기 {second}?</div>
                <form onSubmit={onSubmitForm}>
                    <input ref={inputRef} onChange={onChangeInput} value={value}/>
                    <button>입력!</button>
                </form>
                <div id="result">{result}</div>
            </React.Fragment>
        );
    }
</script>
<script type="text/babel">
     ReactDOM.createRoot(document.querySelector('#root')).render(<div><GuGuDan/></div>);
</script>
</body>
</html>

1-1. Class와 Hooks 비교

Class

Gugudan-class.html

<html>
<head>
    <meta charset="UTF-8"/>
    <title>구구단</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과: <div id="root"><button>Like</button></div> -->
<script type="text/babel">
  class GuGuDan extends React.Component {
    state = {
      first: Math.ceil(Math.random() * 9),
      second: Math.ceil(Math.random() * 9),
      value: '',
      result: '',
    };

    onSubmit = (e) => {
      e.preventDefault();
      if (parseInt(this.state.value) === this.state.first * this.state.second) {
        this.setState((prevState) => {
          return {
            result: '정답: ' + prevState.value, // 정답 값 표시하기 (현재 값) => 현재 state
            first: Math.ceil(Math.random() * 9),
            second: Math.ceil(Math.random() * 9),
            value: '',
            // => 미래 state
          };
        });
        this.input.focus();
      } else {
        this.setState({
          result: '땡',
          value: '',
        });
        this.input.focus();
      }
    };

    onChange = (e) => {
      this.setState({ value: e.target.value });
    };

    input;

    onRefInput = (c) => { this.input = c; };
    // => 함수를 렌더링할 때 마다 만들면 낭비이기 때문에 함수를 따로 빼는 것이 좋다.

    // 컨텐츠
    render() {
        console.log('렌더링'); // setState를 할 때마다 render 함수가 실행된다.
      return (
        <React.Fragment>
          <div>{this.state.first} 곱하기 {this.state.second}?</div>
          <form onSubmit={this.onSubmit}>
            <input ref={this.onRefInput} type="number" value={this.state.value} onChange={this.onChange}/>
            <button>입력!</button>
            {/* <button id="button" className="" htmlFor="">입력!</button> */}
            {/* id 사용 가능 */}
            {/* class : React에서는 class대신 className을 사용해야한다. -> React class랑 헷갈려서 */}
            {/* label의 for 속성 : for대신 htmlFor을 써야한다. -> 반복문의 for과 헷갈린다. */}
          </form>
          <div>{this.state.result}</div>
        </React.Fragment>
      );
    }
  }

</script>
<script type="text/babel">
  ReactDOM.render(<GuGuDan/>, document.querySelector('#root'));
</script>
</body>
</html>
Hooks

index2.html

<html>
<head>
    <meta charset="UTF-8" />
    <title>구구단</title>
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과: <div id="root"><button>Like</button></div> -->
<script type="text/babel">
    // class GuGuDan extedns React.Component {
    //
    // }

    // Hooks : GuGuDan이라는 함수 컴포넌트에 state와 ref기능을 추가해준 것
    const GuGuDan = () => { // 함수 컴포넌트
        const [first, setFirst] = React.useState(Math.ceil(Math.random() * 9 /*초기값*/));
        // 구조 분해 문법 : 변수 자리에다가 배열쓰고 객체쓰고 하는 것 (= 비구조화 할당)
        const [second, setSecond] = React.useState(Math.ceil(Math.random() * 9));
        const [value, setValue] = React.useState('');
        const [result, setResult] = React.useState('');
        const inputRef = React.useRef(null);
        // use로 시작되는 것이 Hooks

         const onSubmitForm = (e) => {
            e.preventDefault();
            if (parseInt(value) === first * second) {
                setResult('정답: ' + value);
                setFirst(Math.ceil(Math.random() * 9));
                setSecond(Math.ceil(Math.random() * 9));
                setValue('');
                inputRef.current.focus();
            } else {
                setResult('땡');
                setValue('');
                inputRef.current.focus();
            }
        }

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

        console.log('렌더링');
        return (
            <React.Fragment>
                <div>{first} 곱하기 {second}?</div>
                <form onSubmit={onSubmitForm}>
                    <input ref={inputRef} onChange={onChangeInput} value={value}/>
                    <button>입력!</button>
                </form>
                <div id="result">{result}</div>
            </React.Fragment>
        );
    }
</script>
<script type="text/babel">
     ReactDOM.createRoot(document.querySelector('#root')).render(<div><GuGuDan/></div>);
</script>
</body>
</html>

끝말잇기

1. 웹팩

  • Node : javascript 실행기

1-1. 웹팩 설치

  1. node랑 npm 설치하기

  2. 터미널에서 폴더 위치 설정하고 npm init 치기

  3. package name, author(이름), license(MIT, ISTC) 설정
    -> package.jsc 생성 : 리액트 개발에 필요한 모든 패키지를 넣는 곳

  4. npm i react react-dom : react랑 react-dom 설치

  5. npm i -D webpack webpack-cli : 리액트할 때 필요한 webpack과 webpack-cli 설치

  • -D : 실제 서비스가 아닌 개발용으로만 웹팩을 사용하겠다는 의미
  • 실제 서비스에서 사용되는 것들
    dependencies에 기록

  • 개발할 때만 사용되는 것들
    devDependencies에 기록

  1. webpack.config.js 생성
module.exports = {
	속성들 넣기
};
  1. client.jsx 생성
const React = require('react');
const ReactDom = require('react-dom');
-> react와 react-dom 불러오기

ReactDom.render(<WordRelay />, document.querySelector('#root'));
  1. index.html 생성
<html>
<head>
    <meta charset="UTF-8" />
    <title>끝말잇기</title>
</head>
<body>
<div id="root"></div>
<script src="./dist/app.js"></script>  
</body>
</html>

1-2. 모듈 시스템과 웹팩 설정

  • 모듈 시스템 덕분에 필요한 것만 불러올 수 있어 효율적이다.
  • 웹팩은 여러 파일을 하나의 파일로 합쳐준다.
client.jsx

const React = require('react');
const ReactDom = require('react-dom');

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

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

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

class WordRelay extends Component {
    state = {

    };

    render() {

    }
}

module.exports = WordRelay;
// 파일을 나눌 때는 const..와 modul..e을 추가적으로 적어준다.
webpack.config.js

// 파일을 하나로 합쳐주는 역할을 함

const path = require('path'); // 경로 조작

module.exports = {
    name: 'wordrelay-setting', // 불필요하지만 속성같은 느낌 : 웹팩에 대한 설명
    mode: 'development', // 실서비스: production
    devtool: 'eval', // 빠르게 하겠다는 뜻
    resolve: {
        extensions: ['.js', '.jsx']
        // 이렇게 하면 확장자를 일일이 쓸 필요 없이 알아서 찾아준다.
    },

    entry: {
        app: ['./client'],
        //app: ['./client.jsx', 'WordRelay.jsx'] -> client.jsx에서 이미 WordRelay.jsx를 불러오고 있기 때문에 굳이 또 적지 않아도 된다.
    }, // 입력 (ex. client.jsx, WordRelay.jsx)
    output: {
        path: path.join(__dirname, 'dist'), // -> 현재 폴더 안에 있는 dist 폴더
        // path.join : 경로를 합쳐줌
        // __dirname : 현재 폴더 경로
        filename: 'app.js'
    }, // 출력 (ex. app.js)
};
// -> 이러고 터미널에 webpack을 치면 파일을 하나로 합친다.

1-3. 웹팩으로 빌드하기

  • 터미널에 webpack을 쳤을 때 오류가 나면 해결하는 방법
    • package.json에서 scripts를 바꿔준다.
      -> 터미널에 npm run dev를 친다.
    • 터미널에 npx webpack을 친다.

1-4. 오류 해결하기

  • app.js를 활용해서 index.html을 실행하면 오류가난다.
    -> babel을 추가해야한다.

  • babel 설치 (개발용에서만 사용)

    • npm i -D @babel/core : babel의 기본적인 것이 들어있다.
    • npm i -D @babel/preset-env : 브라우저에 맞게 최신 문법을 옛날 문법으로 바꿔준다.
    • npm i -D @babel/preset-react : jsx같은 것을 지원할 수 있다.
    • npm i -D babel-loader : babel이랑 webpack을 연결해준다.

  • webpack.config.js

// 파일을 하나로 합쳐주는 역할을 함

const path = require('path'); // 경로 조작

module.exports = {
    name: 'wordrelay-setting', // 불필요하지만 속성같은 느낌 : 웹팩에 대한 설명
    mode: 'development', // 실서비스: production
    devtool: 'eval', // 빠르게 하겠다는 뜻
    resolve: {
        extensions: ['.js', '.jsx']
        // 이렇게 하면 확장자를 일일이 쓸 필요 없이 알아서 찾아준다.
    },

    entry: {
        app: ['./client'],
        //app: ['./client.jsx', 'WordRelay.jsx'] -> client.jsx에서 이미 WordRelay.jsx를 불러오고 있기 때문에 굳이 또 적지 않아도 된다.
    }, // 입력 (ex. client.jsx, WordRelay.jsx)

    module: {
        rules: [{
            test: /\.jsx?/, // js파일과 jsx파일을 이 rule을 적용하겠다는 뜻 (정규 표현식)
            loader: 'babel-loader', // babel rule
            options: {
                presets: ['@babel/preset-env', '@babel/preset-react'], // 알아서 js나 jsx 파일에 babel을 적용해준다.
                plugins: ['@babel/plugin-proposal-class-properties'],
            },
        }],
    }, // -> entry에 있는 파일을 읽고 거기에 module을 적용한 후, output에 뺀다.

    output: {
        path: path.join(__dirname, 'dist'), // -> 현재 폴더 안에 있는 dist 폴더
        // path.join : 경로를 합쳐줌
        // __dirname : 현재 폴더 경로
        filename: 'app.js'
    }, // 출력 (ex. app.js)
};
// -> 이러고 터미널에 webpack을 치면 파일을 하나로 합친다.
WordRelay.jsx


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

class WordRelay extends Component {
    state = {
        text: 'Hello, webpack',
    };

    render() {
        return <h1>{this.state.text}</h1>
    }
}

module.exports = WordRelay;
// 파일을 나눌 때는 const..와 modul..e을 추가적으로 적어준다.

1-5. 구구단 웹팩으로 빌드하기



📚 Referecne

  • 학습 자료 및 그림 출처

    Inflearn - 웹 게임을 만들며 배우는 React (조현영 (제로초))

profile
개린이의 개발 고수되기 작전!

0개의 댓글