들어가기전
React 에서는 직접적인 DOM 의 접근보다는 State 라는 상태 값을 이용하여 DOM 에 변화를 준다고 했습니다.
이번에는 Event 를 학습하여 State 를 다양하게 변경하는 방법에 대해서 알아보려고합니다.
실습
프로젝트는 초기 세팅 상태 로 진행되어집니다. +@ 로 이제는 styled-component 를 이용하기 때문에 App.css 파일이 필요없습니다.
우리가 입력하는 값에 따라서 넓이, 높이, 색상을 가진 박스를 만들어보고자 합니다.
Input 에 값을 입력하여 입력된 값을 바탕으로 상자를 만들고 싶습니다.
먼저 Input, Label Component 를 만들어보겠습니다.
Copy // App.js
import React from 'react'
import styled from 'styled-components'
const Label = styled . h2 `
color: #333;
`
const Input = styled . input `
padding: 10px 20px;
`
class App extends React . Component {
render () {
return (
< div >
< Label >Width</ Label >
< Input />
< Label >Height</ Label >
< Input />
< Label >Color</ Label >
< Input />
</ div >
)
}
}
export default App
Box Component 를 준비합니다. Box 는 넓이, 높이, 색상을 Prop 로 받아 스타일을 구성합니다.
Copy const Box = styled . div `
${ ({ width , height , color }) =>
width && height && color && css `
width: ${ width } px;
height: ${ height } px;
background-color: ${ color } ;
` }
`
이번에는 Box 에게 넘겨줄 State 를 추가합니다.
그리고 추가된 State 를 Box 에게 넘겨줍니다.
Copy // App.js
import React from 'react'
import styled , { css } from 'styled-components'
const Label = styled . h2 `
color: #333;
`
const Input = styled . input `
padding: 10px 20px;
`
const Button = styled . button `
display: block;
background: #03A9F4;
border: none;
color: #fff;
font-weight: bold;
border-radius: 4px;
padding: 5px 10px;
margin-top: 20px;
`
const Box = styled . div `
${ ({ width , height , color }) =>
width && height && color && css `
width: ${ width } px;
height: ${ height } px;
background-color: ${ color } ;
` }
`
class App extends React . Component {
state = {
width : 0 ,
height : 0 ,
color : ''
}
render () {
const { width , height , color } = this .state
return (
< div >
< Label >Width</ Label >
< Input />
< Label >Height</ Label >
< Input />
< Label >Color</ Label >
< Input />
< Box width = {width} height = {height} color = {color} />
</ div >
)
}
}
export default App
우리가 원하는 것은 Input 에 값을 입력하고 Input 에 맞는 State 가 변경이되면서 변경된 값이 Box 에게 전달되기를 원합니다.
Input 의 onChange Event 를 추가하여 바뀌는 값을 캐치해보겠습니다.
Copy // App.js
import React from 'react'
import styled , { css } from 'styled-components'
const Label = styled . h2 `
color: #333;
`
const Input = styled . input `
padding: 10px 20px;
`
const Box = styled . div `
${ ({ width , height , color }) =>
width && height && color && css `
width: ${ width } px;
height: ${ height } px;
background-color: ${ color } ;
` }
`
class App extends React . Component {
state = {
width : 0 ,
height : 0 ,
color : ''
}
handleStyles = (e) => {
console .log ( e .target)
}
render () {
const { state: { width , height , color } , handleStyles } = this
return (
< div >
< Label >Width</ Label >
< Input name = "width" onChange = {handleStyles}/>
< Label >Height</ Label >
< Input name = "height" onChange = {handleStyles} />
< Label >Color</ Label >
< Input name = "color" onChange = {handleStyles} />
< Box width = {width} height = {height} color = {color} />
</ div >
)
}
}
export default App
각 Input 들은 onChange 를 통해 handleStyles 함수를 호출합니다. handleStyles 함수는 event 객체를 넘겨받습니다.
event 객체에는 해당 이벤트에 대한 정보를 담고있습니다.
Input 들은 name 값을 가지고 있고 Input 이기 때문에 value attribute 를 가지고 있습니다.
우리는 이 값들을 이용하여 state 를 변경하려고합니다.
JSX 에서 Event 를 걸어줄때는 함수를 JSX 내부가 아닌 class 아래쪽으로 빼주는 것이 좋습니다.
handleStyles 함수에 넘어오는 event 객체를 통해 Input 의 name 과 value 를 가져옵니다.
Copy // App.js
handleStyles = ({ target: { name , value }}) => {
console .log (name , value)
}
이제 이 값들을 이용해서 State 의 정보를 update 합니다.
State 를 update 할 때는 반드시 setState 라는 함수를 이용해야합니다.
기존의 State 들은 유지하면서 새로 들어온 key, value 값만 update 합니다.
Copy // App.js
handleStyles = ({ target: { name , value }}) => {
this .setState ({ ... this .state , [name] : value })
}
Hook 을 이용하기
hook 은 위에서 알아본 Class Component 와는 살짝 다릅니다.
State 선언과 update는 useState 라는 것을 이용합니다.
Copy // App.js
import React , { useState } from 'react'
import styled , { css } from 'styled-components'
const Label = styled . h2 `
color: #333;
`
const Input = styled . input `
padding: 10px 20px;
`
const Box = styled . div `
${ ({ width , height , color }) =>
width && height && color && css `
width: ${ width } px;
height: ${ height } px;
background-color: ${ color } ;
` }
`
function App () {
const [ styles , setStyles ] = useState ({
width : 0 ,
height : 0 ,
color : ''
})
const handleStyles = ({ target: { name , value }}) => {
setStyles ({ ... styles , [name] : value })
}
const { width , height , color } = styles
return (
< div >
< Label >Width</ Label >
< Input name = "width" onChange = {handleStyles}/>
< Label >Height</ Label >
< Input name = "height" onChange = {handleStyles} />
< Label >Color</ Label >
< Input name = "color" onChange = {handleStyles} />
< Box width = {width} height = {height} color = {color} />
</ div >
)
}
export default App