로그인이라는 컴포넌트를 구현하기 위해서 각각의 기능과 과정을 다음과 같이 나누어야만 했다.
- 기능을 구현하기 위해 필요한 state들을 미리 상정
⬇- 아이디, 패스워드
<input>
칸에 value가 생기면 변화를 감지하는 "onChange"라는 속성 부여
⬇- onChange라는 prop에 의해 유효성 검사를 하는 함수 실행
⬇- 유효성 검사를 하는 함수의 return값에 따라서
<button>
태그에 "disabled"라는 속성값과 "className" 제어
⬇<button>
태그에 "onClick" 속성 부여하고, 유효성검사에 의해 활성화 됐을 경우, 클릭시에 실행될 함수 정의
⬇- "useNavigate" hook을 사용하여 다른 경로의 페이지로 넘어가는 함수 구현
1. 기능을 구현하기 위해 필요한 state들을 미리 상정
전체적인 구조를 생각했을 때, ID <input>
값에 따라서 "setId"의 state가 변하고, 패스워드<input>
값에 따라서 "setPassword"의 state가 변해서 "id"와 "password" 두가지 모두의 state에 따라 "setIsActive"의 state를 변화시키도록 하고 싶다.
const [id, setId] = useState('');
const [password, setPassword] = useState('');
const [isActive, setIsActive] = useState(false);
2. 아이디, 패스워드
<input>
칸에 value가 생기면 변화를 감지하는 "onChange"라는 속성 부여
{/*ID*/}
<input onChange={handleIdInput}
className="id"
type="text"
placeholder="전화번호, 사용자 이름 또는 이메일"
/>
{/* PASSWORD */}
<input onChange={handlePwInput}
className="password"
type="password"
placeholder="비밀번호"
/>
위에서 볼 수 있듯이 ID<input>
칸과 패스워드<input>
칸에 대해서 둘다 "onChange"라는 prop이 부여되어 있고, 각각의 태그가 상위 컴포넌트에서 정의된 함수 "handleIdInput"과 "handlePwInput"이라는 함수를 props로 받고 있다. 그래서 각각의 <input>
태그의 value가 변하면 실시간으로 각각의 함수가 실행되게 된다.
3. onChange라는 prop에 의해 유효성 검사를 하는 함수 실행
실행되게 될 각각의 함수의 형태는 다음과 같다.
{/*아이디의 입력값을 받아 유효성 검사*/}
const handleIdInput = event => {
setId(event.target.value);
if (event.target.value.includes('@') && password.length > 4) {
setIsActive(true);
} else {
setIsActive(false);
}
};
{/*패스워드의 입력값을 받아 유효성 검사*/}
const handlePwInput = event => {
setPassword(event.target.value);
if (id.includes('@') && event.target.value.length > 4) {
setIsActive(true);
} else {
setIsActive(false);
}
};
지금 상기의 두 함수는, 마치 "handelIdInput"이 ID의 유효성을 검사하고, "handlePwInput"이 패스워드의 유효성을 검사하면서 각각의 함수가 ID와 패스워드의 각각의 유효성을 검사하는 것처럼 함수명이 지어졌지만, 사실 내부적으로 들여다보면 각각의 함수가 두가지 값을 모두 교차검사하도록 정의되었다.
원래는 두가지 함수 각각의 결과값이 로그인<button>
태그에 걸린 속성 "className"과 "disabled" 모두에 영향을 줄 수 있도록 만들고 싶었지만,
{/*이런식으로*/}
disabled = {(handleIdInput() && handlePwInput())}
이런식으로는 구현할 수 없기에
#질문1) 라고 쓰면서 생각해보니, 논리연산자인 &&로 "true && true"를 반환하면 true가 반환되니까 되어야 할 것 같은데 질문하여 검증해보자.
결과적으로 각각의 함수의 정의단계에서 서로의 영역을 침범하여 교차검증하고, 각 함수의 결과값에 따라 state값에 변화를 미치도록 설정하였다.
event의 target이 되는 value가 "@"라는 문자열을 포함하고 있고, password 값이 길이가 4이상이면 각각의 state가 변하도록 각각의 함수를 정의하고 있다.
충족하면 -> setIsActive(true)
충족하지 않으면 -> setIsActive(false)
#질문2-1) useState라는 Hook은 배열 형태의 데이터이고, 첫원소는 초기값, 두번째 원소는 초기값을 변화시킬 함수인 것으로 알고 있다. 유효성을 검사하는 함수에서 충족하면 setIsActive(true)라고 되어 있는데 이것은 setIsActive라는 함수에 true라는 인자를 받아온 결과값을 isActive라는 state로 저장하라는 의미일 것이다. 이 의미가 맞는지, 아니라면 의미론적으로 정확한 의미가 무엇인지 setIsActive="true" 등으로 표현하면 어떤 문제가 생기는지 알아보자.
#질문2-2) setIsActive라는 함수에 true혹은 false라는 인자를 받으면 어떤 함수적인 정의에 의해서 어떻게 true 혹은 false의 함수결과값을 받게되는지, 그리고 그러한 함수의 정의가 어디에 나와있는지
답 : 의미적으로 setIsActive(true)의 정확한 의미는 setIsActive라는 함수에 true라는 인자를 넣어 isActiveTrue의 state를 true로 만들겠다는 얘기다. 두가지 질문에 모두 답이 될 수 있다.
4. 유효성 검사를 하는 함수의 return값에 따라서
<button>
태그에 "disabled"라는 속성값과 "className" 제어
"handleIdInput"함수와 "handlePwInput"함수는 각각 "setId"와 "setPassword"의 state를 변화시키고, 두가지의 state가 "setIsActive" state에 영향을 준다. "isActive"의 state를 변화시켜서, 이것을 props로 전달받은 <button>
태그의 "className"속성과 "disabled"속성이 저장된 "isActive"의 state에 따라서 제어되게 된다.
<button
type="button"
className={isActive ? 'activatedBtn' : 'unactivatedBtn'}
disabled={!isActive}
onClick={goToMain}
>
참고)
<button>
태그의 disabled 속성은 해당 버튼이 비활성화됨을 명시.
이 속성을 사용하면 특정 조건이 충족될 때까지 사용자가 특정 조건이 충족될 때까지 사용자가 버튼을 클릭할 수 없도록 설정하고, 특정 조건이 충족되면 자바스크립트 등으로 disabled 속성값을 삭제하여 사용자가 버튼을 다시 사용할 수 있도록 조정할 수 있다.
disabled 속성은 불리언(boolean) 속성이다.
불리언 속성은 해당 속성을 명시하지 않으면 속성값이 자동으로 false값을 가지게 되며, 명시하면 자동으로 true값을 가지게 된다.
const [isActive, setIsActive] = useState(false);
1번 단계에서 설정해둔 useState hook에 의해서 isActive는 초기값이 false고, Boolean형태의 데이터값을 받게 된다.
그리고 isActive 또한 Boolean형태의 데이터가 되게 된다.
5.
<button>
태그에 "onClick" 속성 부여하고, 유효성검사에 의해 활성화 됐을 경우, 클릭시에 실행될 함수 정의
6. "useNavigate" hook을 사용하여 다른 경로의 페이지로 넘어가는 함수 구현
위의 과정에서 <button>
태그에 "onClick" 속성을 부여했고, 그에대한 속성값으로 "goToMain"이라는 변수명을 가진 함수를 할당했다.
const navigate = useNavigate();
const goToMain = () => navigate('/main-jaehong');
페이지간 이동 기능을 구현하기 위해서 "useNavigate"라는 Hook을 사용했고, goToMain이라는 변수에 할당했다.
#질문3)
onClick이라는 prop을 활용하면서 그에 대한 할당값으로 "goToMain"이라는 변수명의 함수를 사용했는데 그 과정에서 { goToMain }이라고 표기했다. "goToMain"이 단순한 문자열데이터가 아니라 표현식이라는 것을 명시하기 위해 JSX에 따라 "{ }" 표현을 쓰는건 알겠는데 만약 "onClick={navigate(/main-jaehong)}"이라고 쓰면 어떻게 되는지가 궁금하다.
답: "onClick"이라는 속성은 속성값으로 함수를 받는다. 함수의 결과값이 아니라.위의 "goToMain"이라는 함수에 "navigate('/main-jaehong/)"라는 함수의 결과값이 할당된 것이다.