useState (state,function)이 실행되는 구조
첫째 인자값은 state를 초기화하는 값
state를 배열로 만들며 state[0]에 'aa'값이 들어가있다.
const state = React.useState('aa')
//['aa', ()=>]와 같다
console.log(state[0]) //aa
두번째 인자값은 state를 변화할때 실행할 함수
console.log(state[1])를 해보면 function 형태가 나오는 것을 볼 수 있다.
따라서 두번째 인자값엔 함수형이 들어간다고 볼 수 있다.
const Form = () => {
const state = React.useState('aa')
console.log(state[0])
const handleSubmit = (e) => {
e.preventDefault()
state[1]('bbb')
}
return(
<form onSubmit={handleSubmit}>
{/* userid 상태와 password 상태값을 alert로 띄우고싶음 */}
<ul>
...
</form> )}
export default Form
useState의 구조
위에서 사용한 코드에 state('bbb')를 추가했을뿐인데, 페이지는 무한반복이 되어버린다.
왜? 클래스 컴포넌트와 함수 컴포넌트의 실행 구조가 다르기 때문이다.
한번 실행시킨 뒤 재실행된 클래스 컴포넌트는 수정된 state값을 실행한 후, 바로 render()안의 코드를 읽는다.
반면에 함수 컴포넌트는 실행될때마다 내부 코드를 전부 실행한다.
const Form = () => {
const state = React.useState('aa')
state[1]('bbb') {/* state 수정 */}
...}
코드를 읽어보면, Form 컴포넌트의 첫째줄에서는 state를 'aa'라고 값을 초기화한다.
두번째 줄에서 state[1]값은 'bbb'라고 수정된다.
state값이 수정될때마다 호출되는 속성을 가진 useState는 다시 처음부터 코드를 읽어내려간다.
첫째줄을 읽고 state값은 다시 'aa'로 초기화 된다.
이 순서를 계속 반복하기때문에 무한반복 상태가 되는 것이다.
useState 코드의 축약형
위에서 설명한 것을 토대로 작성한 코드를 구조분해할당을 통해 축약하면 다음과 같은 코드가 나온다.
const Form = () => {
const state = React.useState('aa') //['aa', ()=>{}]
const values = state[0]
const setValues = state[1]
//구조분해할당을 통한 코드축약
//const [values,setValues] = React.useState('aa')
회원가입 기능 만들어보기
내가 이해한 input에 키보드 입력 이벤트 발생부터
입력창에 입력한 글자가 뜨는게 브라우저에 렌더링 될때까지의 흐름.
이게 머리속에 그려지는게 시간이 좀 걸려서 나중에 볼때 한번에 알 수 있도록 그려보았다.
const Form2 = () => {
const state = React.useState('aa') //['aa', ()=>{}]
const [userid, setUserid] = useState('')
const [password, setPassword] = useState('')
const handleSubmit = (e) => {
e.preventDefault()
}
const changeUserid = e => {
const value = e.target.value
setUserid(value)
}
const changePassword = e => {
const value = e.target.value
setPassword(value)
}
return(
<form onSubmit={handleSubmit}>
{/* userid 상태와 password 상태값을 alert로 띄우고싶음 */}
<ul>
<h2>회원가입</h2>
<li>
// input의 이름을 적는 lable
// input의 id/name을 적는 htmlFor
<label htmlFor="userid">아이디</label>
<input type="text" name="userid" onChange={changeUserid} value={userid}/>
{/* onChange가 일어날때마다 최신화로 바꾸기 */}
</li>
<li>
<label htmlFor="password">비밀번호</label>
<input type="text" name="password" onChange={changePassword} value={password}/>
{/* onChange가 일어날때마다 최신화로 바꾸기 */}
</li>
<li>
<input type="submit" value="가입" />
</li>
</ul>
</form>
)
}
두개의 함수를 하나의 함수로 만들기
changeUserid와 changePassword 기능을 둘 다 수행할 수 있는 handleChange를 만들었다.
const state = React.useState('aa') //['aa', ()=>{}]
const [userid, setUserid] = useState('')
const [password, setPassword] = useState('')
const [values,setValues] = useState({userid:'',password:''})
const handleSubmit = (e) => {
e.preventDefault()
}
const handleChange = e => {
const value = e.target.value
const name = e.target.name
//{userid:'',password:'', userid:'asdf'}
//key값이 겹치기때문에 userid는 최신화된다.
//즉, {password:'', userid:'asdf'}
setValues({...values,[name]:value})
}
// const changeUserid = e => {
// const value = e.target.value
// setUserid(value)
// }
// const changePassword = e => {
// const value = e.target.value
// setPassword(value)
// }
Custom Hook
커스텀훅을 사용하기 위한 사전지식
<input />은 사실 객체형태로 된 자바스크립트다.
그래서 bable을 통해 실행되고 있다.
//객체로 된 자바스크립트의 예
{
type:'input',
props:{
type:'input',
name:'userid',
onChange:()=>{},
value:'aaaa'
}
}
확인해보기
let obj={ value:'44444' }
return(
<form onSubmit={handleSubmit}>
<ul>
<h2>회원가입</h2>
<li>
<label htmlFor="userid">아이디</label>
<input type="text" name="userid" {...obj}/>
//{...value}는 {value:'44444'}와 같다
...
type='text'나 name:'userid'는 원래 객체형태인데 값이 하나밖에 없으니까 중괄호를 벗기고 쓰는것임.
하지만 이게 원래 객체형태인걸 알게되면 좀더 활용적이게 쓸 수 있다.
let obj={
value:userid,
onChange:changeUserid
}
이렇게만 작성해도 input에 입력한 키값이 표시된다.
Custom Hook을 함수로 만들기
함수로 만들어 놓으면 필요할때 호출만 하면 되기때문에 편하다
const useInput = () => {
return{
value:'오리는 퐁실퐁실',
onChange:(e)=>{
console.log(e.target.value)
}
}
}
...
<input type="text" name="userid" {...useInput()}/>
...
상태값을 가진 Hook으로 만들기
Hook의 장점은 어떤 함수던지 함수 안에서 상태를 만들 수 있다는 점이다.
방금 위에서 만든 함수 안에 상태값을 만들어서 코드를 만들었다.
const useInput = (defaultValues) => {
const [value,setValue] = useState(defaultValues)
const onChange = (e) => {
setValue(e.target.value)
}
return{
value, // value:value 니까 생략해서
onChange //onChange도 같은 이유로 생략
}
}
...
const Form = () => {
// useInput에 상태를 만들어서 필요없음
// const state = React.useState('aa') //['aa', ()=>{}]
const [userid, setUserid] = useState('')
const [password, setPassword] = useState('')
const id = useInput() //id라는 객체 생성 {return{value,onChange}}
const pw = useInput() //pw라는 객체 생성
...
return(
<input type="text" name="userid" {...id}/>
<input type="text" name="password" {...pw}/>
...
개발자 모드에서 Hook 확인하기
'프로그래밍 > react' 카테고리의 다른 글
[220427] 코드의 분리 (0) | 2022.05.04 |
---|---|
[220426] 회원가입창 만들기 / useEffect (0) | 2022.05.03 |
[220425] 함수컴포넌트로 로그인기능 생성, props 값 넘기기 (0) | 2022.05.02 |
[220425] 함수형 컴포넌트, Hook, useState, useEffect (0) | 2022.05.01 |
[220422] 리액트로 덧글기능 만들기 (CRUD 중 UD), 생명주기함수 (0) | 2022.04.29 |
댓글