React 스터디 1주차
🎮 웹 게임을 만들며 배우는 React
1주차: 구구단
1. React를 쓰는 이유?
사용자 인터페이스 및 양질의 사용자 경험을 제공할 수 있으며 싱글 페이지 애플리케이션(SPA), 즉 한 개의 페이지로 이루어진 애플리케이션을 만드는 데 용이하다. 또한, 데이터와 화면의 일치를 리액트가 자동으로 도와준다. 마지막으로 중복되는 컴포넌트를 하나로 묶어주는 것이 가능하여 유지보수가 편리하다는 장점 또한 있다.
2. 컴포넌트 생성
코드가 비효율적으로 느껴질 수 있으나, 이는 리액트의 동작 원리를 알아보기 위함이다.
https://ko.reactjs.org/docs/cdn-links.html 에서 CDN 링크를 가져왔다.
이때
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
이는 react가 동작하기 위한 핵심적인 파일이 들어 있는 자바스크립트이며
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
이 react-dom은 리액트 코드를 웹에 붙여주는 역할이라고 이해하면 된다.
<!DOCTYPE html>
<html>
<head>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<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);
}
render() {
// LikeButton을 화면에 어떻게 표시할 것인지
return e('button', null, 'Like'); // <button>Like</button>을 만들겠다!
}
}
</script>
<script>
ReactDOM.render(e(LikeButton), document.querySelector('#root')); // 컴포넌트를 root 내에 그림
</script>
</body>
</head>
</html>
예측한대로 button이 생성되었다!
이때 button에 onClick 속성을 부여해 보자. (이때 Html의 속성을 JS로 표현할 시에는 Camel Case를 이용해야 한다.)
render() {
// LikeButton을 화면에 어떻게 표시할 것인지
return e('button', {onClick: () => {console.log('clicked')}, type: 'submit'}, 'Like'); // <button>Like</button>을 만들겠다!
}
개발자 도구의 콘솔 로그에 clicked가 남는다.
이제 상태(state)를 변경해 보자. 이때 상태는 바뀌는 부분, 또는 바뀔 수 있는 부분을 의미한다. 버튼을 클릭하면 Like를 Liked로 변경하자.
constructor(props) {
super(props);
this.state = {
// 상태
liked: false,
};
}
render() {
// LikeButton을 화면에 어떻게 표시할 것인지
return e('button', {onClick: () => {this.setState({ liked: true })}, type: 'submit'},
this.state.liked === true ? 'Liked' : 'Like',); // <button>Like</button>을 만들겠다!
}
}
클릭 시에 상태에 따라 Like가 Liked로 변한다. 상태를 데이터라고 가정했을 시에 데이터를 화면에 보여주는 것의 예시라 할 수 있다.
3.JSX와 바벨(babel)
최신 문법 등을 JS에서 사용할 수 있게 해 주는 babel을 이용한다.
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
그러면 다음과 같이 JS 내에서 html 태그 문법의 사용이 가능하다.
render() {
// LikeButton을 화면에 어떻게 표시할 것인지
return <button type="submit" onClick={() =>{this.setState({ liked: true })}}>
{this.state.liked === true ? 'Liked' : 'Like'}
</button>
// JSX
}
}
</script>
<script>
ReactDOM.render(<LikeButton />), document.querySelector('#root')); // 컴포넌트를 root 내에 그림
</script>
이때 JSX라는 개념이 등장하는데, 이 JSX는 JS + XML의 개념이라고 한다.
4. 구구단
<body>
<div id="root"></div> <!-- 결과: <div id="root"><button>Like</button></div> -->
<script type="text/babel">
class GuGudan extends React.Component {
constructor(props) {
super(props);
this.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 ({
result: '정답!',
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
});
}
else {
this.setState({
result: '땡!',
value: '',
})
}
};
onChange = (e) => {
this.setState({ value: e.target.value })
};
render() {
return (
<div>
<div> {this.state.first} 곱하기 {this.state.second}은? </div>
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value}
onChange={this.onChange}/>
<button>입력!</button>
</form>
<div>{this.state.result}</div>
</div>
);
}
}
</script>
<script type="text/babel">
ReactDOM.render((<GuGudan />), document.querySelector('#root')); // 컴포넌트를 root 내에 그림
</script>
</body>
+)
이때
이와 같이 쓸데없는 div를 없애고 <>...</> 만으로 처리할 수 있다.
++)
constructor... 부분을 제외하고, state만 선언해서 사용하는 것이 가능하다.
+++)
이전의 상태를 표현할 시에는 다음과 같다.
if(parseInt(this.state.value) === this.state.first * this.state.second) {
this.setState ((prevState) => { // 이전 상태 표현
return {
result: prevState.first + ' X ' + prevState.second + ' = ' + prevState.value + ' 정답! ',
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
}
});
}
// 이전 state로 새로운 state 값을 만들 때에는 return을 사용
++++)
입력 후 focus를 주려면 다음과 같다.
if(parseInt(this.state.value) === this.state.first * this.state.second) {
this.setState ((prevState) => { // 이전 상태 표현
return {
result: prevState.first + ' X ' + prevState.second + ' = ' + prevState.value + ' 정답! ',
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
}
});
this.input.focus();
}
// 이전 state로 새로운 state 값을 만들 때에는 return을 사용
else {
this.setState({
result: '땡!',
value: '',
})
this.input.focus();
}
};
onChange = (e) => {
this.setState({ value: e.target.value })
};
input;
onRefInput = (c) => { this.input = c; };
// state가 바뀔 때마다 render가 실행되므로 함수를 바깥에 선언하는 것이 좋다.
render() {
return (
<>
<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}/>
추가
1.
3번 항목을 수강하던 도중 이와 같은 오류가 발생했다. element를 읽을 수 없어 발생하는 오류라고 한다.
ReactDOM.render 뒤에 괄호가 빠져 있었다. 😥
2.
1.7강 과제
{...}
result: this.state.first + ' X ' + this.state.second + ' = ' + this.state.value + ' 정답! ',
{...}
📖 이용 강의
https://inf.run/gcb2 웹 게임을 만들며 배우는 React
Author And Source
이 문제에 관하여(React 스터디 1주차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@artian99/React-스터디-1주차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)