728x90
오늘 내가 배운 것
1. 카운터 만들기
2. componentDidMount, state를 이용하여 loading 구현하기
3. loading 후 증감 하는 버튼 만들기
4. 배열로 들어온 데이터 렌더하는 방법 (List)
5. this 바인딩하는 방법
1. 카운터 만들기
+버튼을 누르면 increment 함수를 이용해서 상태를 +1 해주고, -버튼을 누르면 decrement 함수를 이용해서 상태가 -1 된다.
처음 랜더 했을 경우 초기값이 10이 뜨는데 어떤 순서에 의해서 10이 되는지를 알아야 한다. 실행되자마자 10으로 세팅되는 것이 아니다.
1-1. 최초 실행 순서
- constructor()가 실행되면서 상태의 number는 0인 상태가 된다.
- number가 0 인 상태로 render()가 실행된다.
- 이후 Count 컴포넌트가 마운트 되면서, componentDidMount()가 호출되고 setState()에 의해 number가 10으로 바뀐다.
- 상태가 바뀌었으므로 render()를 실행하여 this.state.number가 10이 된다.
위에 실행 순서에 의해 최소 실행 시 사용자가 보이는 화면에 10으로 보이는 것을 알고 있어야 한다.
1.2. "+"버튼 눌렀을 때 코드 실행 순서
- onClick에 의해 increment() 호출이 된다.
- state.number의 값이 변경되고, render() 실행되면서 값이 업데이트된다.
- componentDidUpdate() 호출이 된다.
2. componentDidMount, state를 이용하여 loading 창 구현하기
2-1. loading 창 코드 실행 순서
- constructor 함수가 실행되면서 loading은 true, number는 0 상태가 된다.
- 이후 render()가 실행되며 조건식에 의해 `로딩 중...`이라는 글자가 랜더 된다.
- render()가 실행된 후 componentDidMount()가 호출되는데, 이때 setTimeout에 의해서 setState함수가 1초 뒤에 실행된다.\
- 1초 뒤 setState 함수가 실행되며 loading이 false, number가 10이 된다.
- 이 상태로 render()가 다시 실행된다.
3. loading 후 증감 하는 버튼 만들기
코드는 2번을 참고
Button 컴포넌트로 밑에 컨트롤러를 하나 더 만든다.
누르면 로딩 중이라는 문구가 뜨고 일정시간 후 로딩 중이라는 문구가 사라지면서 숫자가 바뀐 상태로 보이기 위한 버튼을 만들 예정이다.
3-1. 코드 실행 순서
- 버튼을 누르면 setLoading 함수가 호출된다.
- setLoading에 의해 loading이 `true`로 바뀌고, 조건식에 따라 increment와 decrement를 호출한다.
- 이후 render()을 호출하는데 loading이 true이기 때문에 `로딩 중..`이 보이고,
상태가 바뀌었으므로 componentDidUpdate()가 호출된다. - componentDidUpdate()는 1초 뒤 loading의 상태를 false로 바꿔준다.
4. 배열로 들어온 데이터 렌더하는 방법 (List)
React에서 state에 [{},{},{}..] 배열 안에 객체로 항목이 있을 경우
이를 map()를 이용해서 JSX 문법으로 변환하면 랜더를 할 수 있다.
<body>
<div id="root"></div>
<script type="text/babel">
class List extends React.Component {
constructor(props) {
super(props)
this.state = {
board: [
{ id: 1, subject: "baekspace1" },
{ id: 2, subject: "baekspace2" },
{ id: 3, subject: "baekspace3" },
{ id: 4, subject: "baekspace4" },
],
}
}
getList(board) {
return this.state.board.map((v) => <li key={v.id}>{v.subject}</li>)
}
render() {
return <ul>{this.getList(this.state.board)}</ul>
}
}
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<List />
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
5. this 바인딩하는 방법
함수를 호출할 때 `this`가 가리키는 객체를 지정하지 않으면 호출하는 방법에 따라 `this`가 가리키는 객체가 달라진다. 그렇기 때문에 함수를 호출할 때, `this`가 항상 같은 객체를 가리키도록 하기 위해서 바인딩을 해줘야 한다.
decrement 함수로 this 바인딩하는 방법 몇 가지를 보면
방법 1. 화살표 함수 이용하기
decrement = () => {
this.setState({ number: this.state.number - 1 })
}
render () {
return (
<button onClick={this.decrement}> - </button>
)
}
방법 2. 이벤트 핸들러 함수를 화살표 함수로 이용하기
decrement2() {
this.setState({ number: this.state.number - 1 })
}
render () {
return (
<button onClick={()=>this.decrement2()}> - </button>
)
}
방법 3. 생성자 함수에서 바인딩하기
constructor (props) {
super(props)
this.decrement3 = this.decrement3.bind(this)
}
decrement3() {
this.setState({ number: this.state.number - 1 })
}
render () {
return (
<button onClick={this.decrement}> - </button>
)
}
더보기
Counter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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/babel.min.js"></script>
<title>Document</title>
<style>
h1 {
text-align: center;
}
.counter {
display: flex;
justify-content: center;
flex-direction: column;
width: 150px;
margin: 0 auto;
}
h2 {
text-align: center;
}
button {
width: 50px;
height: 30px;
margin: 0 10px;
font-size: 25px;
}
</style>
</head>
<body>
<h1>카운터 만들기</h1>
<div id="root"></div>
<script type="text/babel">
class Button extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<button onClick={this.props.setLoading}>+</button>
<button onClick={this.props.setLoading}>-</button>
</div>
)
}
}
class Count extends React.Component {
constructor(props) {
super(props)
this.state = {
number: 0,
loading: true,
}
}
componentDidMount() {
setTimeout(() => {
this.setState({ number: 10, loading: false })
}, 1000)
}
componentDidUpdate() {
if (this.state.loading === true) {
setTimeout(() => {
this.setState({ loading: false })
}, 1000)
}
}
setLoading = (e) => {
this.state.loading = true
if (e.target.innerHTML === "+") {
this.increment()
} else {
this.decrement()
}
}
increment = () => {
this.setState({ number: this.state.number + 1 })
}
decrement = () => {
this.setState({ number: this.state.number - 1 })
}
render() {
if (this.state.loading) return <h1>로딩중..</h1>
return (
<div className="counter">
<h2>{this.state.number}</h2>
<div className="counterBtn">
<button onClick={this.increment}> + </button>
<button onClick={this.decrement}> - </button>
<br />
<br />
Loadding
<br />
<br />
<Button setLoading={this.setLoading} />
</div>
</div>
)
}
}
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<Count />
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
</html>
List
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class List extends React.Component {
constructor(props) {
super(props)
this.state = {
board: [
{ id: 1, subject: "baekspace1" },
{ id: 2, subject: "baekspace2" },
{ id: 3, subject: "baekspace3" },
{ id: 4, subject: "baekspace4" },
],
}
}
getList(board) {
return this.state.board.map((v) => <li key={v.id}>{v.subject}</li>)
}
render() {
return <ul>{this.getList(this.state.board)}</ul>
}
}
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<List />
</div>
)
}
}
const root = ReactDOM.createRoot(document.querySelector("#root"))
root.render(<App />)
</script>
</body>
</html>
반응형
'시작 > TIL(Today I Learned)' 카테고리의 다른 글
230227 - Babel ( 바벨 ) (1) | 2023.02.27 |
---|---|
230224 - React TicTacToe(틱택토) 게임 만들기 (0) | 2023.02.24 |
230222 - React Comment 만들기 (0) | 2023.02.22 |
230221 - React (리액트) 기초 (0) | 2023.02.21 |
230220 - 프로젝트 발표 및 회고 (0) | 2023.02.21 |
댓글