만족은 하되 안주하지는 말자

기록해야 기억한다

프로그래밍/frontend

[React] 리액트로 구구단 웹 페이지를 만들어보자

D36choi 2020. 8. 2. 00:30
728x90

https://www.inflearn.com/course/web-game-React/dashboard

 

웹 게임을 만들며 배우는 React - 인프런

웹게임을 통해 리액트를 배워봅니다. Class, Hooks를 모두 익히며, Context API와 React Router, 웹팩, 바벨까지 추가로 배웁니다. 초급 웹 개발 프레임워크 및 라이브러리 React 웹 개발 게임개발 온라인 강�

www.inflearn.com

'제로초' 님의 무료 강의를 바탕으로 만들었습니다.

 

준비: 폴더를 하나 만들어, gugudan.html 을 만들자 (필요하다면 style.css 도)

 

번거롭고 보기 복잡한 형태의 Like 버튼 예제

<html>
    <head>
        <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>
    </head>
    <body>
        <div id="root"></div> <!-- <div id="root><button>Like</button></div> 이 될것임을 예측가능.-->
        <script>
            const e = React.createElement;

            class LikeButton extends React.Component {
                constructor(props){
                    super(props);
                    this.state = {
                        liked: false, // 기본상태
                    }
                }
                render(){ // 2nd param : 속성넣는 자리, 속성은 camel case 로 써야한다.
                    return <button type="submit" onClick={()=> { this.setState({liked:true})}}>Like</button>;
                    // return e('button',
                    //  { onClick: ()=> {this.setState({liked: true})}, type:'submit' }, 
                    //  this.state.liked === true ? 'Liked' : "unLiked");
                } // 상태는 바뀌는 부분이다. (state)
            }
        </script>
        <script>
            ReactDOM.render(<LikeButton/>, document.querySelector('#root'));
        </script>
    </body>
</html>

강의자님 말씀으론, 이 코드를 보고 불편함을 느끼는 것부터 시작해야 이후에는 차근차근 더 발전되고 가시성이 좋은 형태로 바뀜을 체감할 수 있다고 한다.

위 코드는 작동이 되지 않는다. 이유는?

위의 return <button... 을 자바스크립트에서는 당연히 지원안해주기때문에

그래서 필요한것이 babel.js

 

그래서 babel.js 를 스크립트로 포함해야 한다

<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

이러면 동작가능!

 

component 의 장점은? 재사용!

<script type="text/babel">
            ReactDOM.render(
                <div>
                    <LikeButton/>
                    <LikeButton/>
                </div>
                , document.querySelector('#root'));
</script>

이렇게, 만들어져있는 컴포넌트를 재사용하면 각기 다른 state 를 가친 객체를 재활용 가능하다!

이경우에는 like 버튼이 2개 생성된다.

 

 

구구단을 만들자

<html>
    <head>
        <meta charset="UTF-8"> 
        <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>
        <script type="text/babel">

            class GuGuDan extends React.Component {
                constructor(props){
                    super(props);
                    this.state = {
                        // 바뀌는 놈들은 state로
                        first : Math.ceil(Math.random() * 9),
                        second : Math.ceil(Math.random() * 9),
                        value : '',
                        result : '',
                    };
                }
                render(){ 
                    return (
                        <div>
                            <div>{this.state.first}곱하기{this.state.second} 는? </div>
                            <form>
                                <input type="number" value={this.state.value}/>
                                <button>제출</button>
                            </form>
                            <div>{this.state.result}</div>
                        </div>
                    ); 
                        
                   
                } // 상태는 바뀌는 부분이다. (state)
            }
        </script>
        <script type="text/babel">
            ReactDOM.render(
                <div>
                    <GuGuDan/>
                </div>
                , document.querySelector('#root'));
        </script>
    </body>
</html>
이대로 만들게 되면, 문제는 input 에 숫자를 입력하고싶어도 입력되지가 않는다 .
 
<form>
    <input type="number" value={this.state.value}
    onChange={(e) => this.setState({ value : e.target.value})}
    />
    <button>제출</button>
</form>

그래서 이렇게 "onChange" 메소드를 통해서만 실시간으로 state 가 변화대로 변동되게 된다!

 

제출을 구현하자

<form onSubmit={(e)=> {
    e.preventDefault();
    if(parseInt(value) === this.state.first * this.state.second) {
        this.setState({
            result: '정답',
            first: Math.ceil(Math.random()*9),
            second: Math.ceil(Math.random()*9),
            value: '',
        });
    } else {
        this.setState({
            result: '땡',
            value: '',
        });
    }
}}>

이대로 한다면, 제출버튼을 누를경우 정답을 구분해 정답인지 아닌지를 텍스트로 출력하게 된다.

 

중요한 개발 원칙을 지키자

<form onSubmit={this.onSubmit}>

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

위와 같이, 메소드를 구분지어서 만들어놓자. html은 HTML 끼리 JS는 JS 끼리 분리해서 만들어야 가독성이 향상된다.

 

 

나만의 커스텀해보기

강사님이 가르쳐주진 않지만, 예전의 웹페이지 개발지식을 복기할 겸, 스스로 CSS 파일을 만들어 예쁘게 꾸며보았다.

 

.template {
    background: white;
    width: 512px;
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); /* 그림자 */ 
    margin: 0 auto; /* 페이지 중앙 정렬 */
    margin-top: 4rem;
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
  }
  
.template .title {
    padding: 2rem;
    font-size: 2.5rem;
    text-align: center;
    font-weight: 100;
    background: #3066BE;
    color: white;
  }
.template .result {
    flex: 1;
    text-align: center;
    font-weight: 600;
    padding: 1.5rem;
    background: #119DA4;  
    color: #fff;
    font-size: larger;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}
.template form {
    display: flex;
    padding: 2rem;
    font-size: 1.0rem;
    text-align: center;
    font-weight: 100;
    background: #6D9DC5;
    color: white;
  }
.template form input {
    flex: 1;
    font-size: 1.5rem;
    text-align: center;
    font-weight: 300;
    border-radius: 4px;
    border: none;
  }
.template form button {
    color: #fff !important;
    font-weight: bolder;
    background: #AEECEF;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    padding-left: 1rem;
    padding-right: 1rem;
    margin-left: 1rem;
    border: none;
    border-radius: 4px;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    /* border-color: #80DED9;
    background: #AEECEF; */
  }
  

.template 은 HTML tag의 class 명을 지정해주어야 적용된다!

 

 

동일 디렉토리에 만든 style.css 파일을 html에 적용하려면 아래와 같은 태그를 <head></head> 사이에 기입한다.

<link rel="stylesheet" href="style.css">

 

결과물