4개의 input값을 참조에 회원가입 버튼이 활성/비활성화 되는 동작을 구현하려했다.
setState를 사용하여 각 input의 name값으로 값에 접근하여 변경 할 수 있도록 잘 처리했다고 생각했다.
그런데 문제가 생겼다.
4개의 input에 키보드 이벤트가 발생할때마다 값을 콘솔에 찍었는데
하나씩 값이 밀려 찍힌다. 이러면 정확하게 가입하기 버튼의 동작을 제어할수 없는데..
구글링, 아무나잡고 물어보기를 시전하여 setState가 비동기라는 사실을 알게되었다.
때문에 내가 값을 변경하면 console.log가 먼저 실행되고 비동기로 대기중이었던 setState의 동작이 나중에 실행되는것이었다.
const SignUp = () => {
const inputsObj = {
user_email: '',
user_nick: '',
user_pw: '',
user_check_pw: ''
}
const [inputValues, setInputs] = useState(inputsObj)
const [isPass, setPass] = useState(true)
useEffect(() => {
checkInputValid()
}, [])
const checkInputValid = () => {
const pass = Object.values(inputValues).some(value => value === '')
setPass(pass)
}
const handleKeyUpInput = (e) => {
setInputs({
...inputValues,
[e.target.name]: e.target.value
})
console.log(inputValues)
}
const handleClickSignUp = () => {
console.log(inputValues)
}
return (
<SignUpArea>
<Grid
is_container
margin="50px auto 10px auto"
padding="30px 40px"
border="border: 1px solid var(--border-color)"
bg="#fff"
>
<Logo maxWidth="180px" margin="0 auto 30px auto"/>
<Text size="16px" color="#aaa" margin="0 0 20px 0" center bold>
매거진스타그램에 가입하세요!
</Text>
<Grid margin="0 0 6px 0">
<Input _onKeyUp={handleKeyUpInput} name="user_email" type="text" placeholder="사용자 이메일" />
</Grid>
<Grid margin="0 0 6px 0">
<Input _onKeyUp={handleKeyUpInput} name="user_nick" type="text" placeholder="닉네임" />
</Grid>
<Grid margin="0 0 6px 0">
<Input _onKeyUp={handleKeyUpInput} name="user_pw" type="password" placeholder="비밀번호" />
</Grid>
<Grid margin="0 0 14px 0">
<Input _onKeyUp={handleKeyUpInput} name="user_check_pw" type="password" placeholder="비밀번호 확인" />
</Grid>
<Grid>
<Button _onClick={handleClickSignUp} width="100%" size="15px" bold disabled={isPass}>가입하기</Button>
</Grid>
</Grid>
<Grid
is_flex
is_container
padding="20px 40px"
border="border: 1px solid var(--border-color)"
bg="#fff"
>
계정이 있으신가요? <Button ver="white" size="15px" bold>로그인</Button>
</Grid>
</SignUpArea>
)
}
이전 클래스형 컴포넌트에서는 setState의 두번째 인자 값으로 변경이 된 상태값에 접근이 가능하였다.
<button
onClick={() => {
this.setState({ number: number - 1 }, () => { //변경된 부분2
console.log(this.state);
this.alertNumber();
});
}}
>
-1
</button>
그러나 내 코드는 함수형 컴포넌트에서 hooks를 사용하고있는데 이때의 setState는 두번째 인자를 지원하지 않았다.
이런 문제는 useEffect()로 해결이 가능하였다. useEffect()의 두번째 인자로 배열에 감시하고자 하는 값을 참조하게하면 상태가 변할때의 값을 정확히 참조 할 수있기 때문에 키보드 이벤트 발생시에 checkInputValid를 실행하게하면 해결 할 수 있는 문제였다.
또, 다른 조언 중에 useCallback()으로도 해결이 가능하다고 했는데 useCallback을 한번도 사용해보지 못했고 어떤 개념인지 몰랐기 때문에 앞으로 공부해봐야겠다.
useEffect() 잘 사용하고, useCallback() 공부해