React에서 데이터가 변하면 렌더링도 바뀌어야한다.
그런데 데이터는 객체로 전달이 된다.
이 객체의 변화를 컴퓨터가 인식하도록 할 수 있어야 렌더링을 바꿀 수 있는데,
이 글에서는 이에 대해 몇 가지 예시를 들어 공부해보도록 한다.
다음과 같이 html을 작성해보자.
<!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">
<title>Document</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.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 Login extends React.Component{
render() {
return (
<button onClick={alert('clicked!')}>press this</button>
)
}
}
class App extends React.Component{
render() {
return (
<div>
<Login/>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.querySelector('#root')
)
</script>
</body>
</html>
<App/>안에 <Login/> component를 넣고 그 안에 button element을 넣었다.
button element에는 click시 발동하는 알람을 세팅해두었다.
그런데 이 html을 브라우저에서 열어보면 클릭을 안했는데도 불러오자마자 알람이 뜨는 것을 알 수 있다.
이는 브라우저가 html을 그리는 과정에서 함수가 실행되기 때문이다.
이를 해결하려면 새 함수를 만들어서 해당하는 함수를 감싸버리는 방법이 있다.
함수를 선언만 된 상태로 바꿔준다고 생각하면 된다.
다음과 같이 <Login/> 컴포넌트를 수정해보자.
class Login extends React.Component{
render() {
return (
<button onClick { () => { alert('clicked') } } >
press this!
</button>
)
}
}
이렇게 alert를 익명함수 안에 넣어주면 버튼을 클릭할 때만 실행되도록 해줄 수 있다.
이제 Login 컴포넌트에 변수를 하나 선언해주자. 선언되는 위치에 주의할 것.
class Login extends React.Component{
state = {
name: 'lsj'
}
render() {
return (
<button onClick { () => { alert('clicked') } } >
press this!
</button>
)
}
}
컴포넌트의 코드블럭 안에 state라는 변수를 선언해줄 수 있다.
변수 이름은 반드시 state로 사용해야 한다. 다른 변수는 먹히지 않는다.
이 state라는 변수를 render의 안으로 가져오는데, 이대로가 아니라 데이터를 추가해서 가져오고 싶다.
이를 위해 spread 연산자를 활용해 객체의 값을 복사해온다.
class Login extends React.Component{
state = {
name: 'lsj'
}
render() {
const obj = {
...this.state,
switch: !this.state.switch
}
return (
<button onClick { () => { alert('clicked') } } >
press this!
</button>
)
}
}
우선 state의 값을 가져온 후, 거기에 switch라는 key와 value를 추가해주었다.
이를 이용해 클릭시마다 값이 바뀌는 버튼을 만들 수 있다.
switch를 클릭시 true/false가 변하도록 , 그리고 그 값에 따라 버튼의 텍스트가 달라지도록 해보자.
JS라면 조건문을 사용하면 되지만 여기선 if문이 없다.
그 대용으로 삼항연산자를 사용한다.
class Login extends React.Component{
state = {
name: 'lsj'
}
render() {
const obj = {
...this.state,
switch: !this.state.switch
}
return (
<button onClick { () => { this.setState(obj) } } >
{this.state.switch ? 'off' : 'on'}
</button>
)
}
}
주목해야 할 것은 화살표 함수 안의 this.setState( ) 함수인데, 이는 state라는 변수를 바꿔주는 함수이다.
그렇기 때문에 반드시 변수 명은 state여야 한 것이다.
이제 버튼을 클릭하면 > setState 함수가 발동해 obj의 값을 바꾸고,
이에 따라 true/false값이 변하면서 'off', 'on' 이 번갈아 버튼의 텍스트로 렌더링된다.
비슷한 예시로 숫자를 카운트하는 기능을 구현해보자.
<!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">
<title>Document</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.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 Counter extends React.Component{
state = {
number : 0
}
incre = (index) => {
const increase = {
...this.state,
number: this.state.number + index
}
this.setState(increase)
}
decre = (index) => {
const decrease = {
...this.state,
number: this.state.number - index
}
this.setState(decrease)
}
render() {
return (
<div>
<h3>{this.state.number}</h3>
<button onClick = { () => {this.incre(1)} }>+</button>
<button onClick = { () => {this.decre(1)} }>-</button>
</div>
)
}
}
class App extends React.Component{
render() {
return(
<div>
<Counter/>
</div>
)
}
}
ReactDOM.render(
<App/>,
document.querySelector('#root')
)
</script>
</body>
</html>
'React' 카테고리의 다른 글
#6 Styling (0) | 2022.04.22 |
---|---|
#5 Webpack (0) | 2022.04.22 |
#4 tictectoe 게임 만들기 (0) | 2022.04.17 |
React #2 Class Component (0) | 2022.04.13 |
React #1 Intro (0) | 2022.04.12 |