๐จ ๋ฌธ์ ์ํฉ
setState๋ฅผ ํตํด ์ํ๊ฐ์ ๋ณ๊ฒฝํ๋ ์ํ๋ ๊ฐ์ด ํ๋์ฉ ๋ฐ๋ฆฐ ์ฑ ๋ณ๊ฒฝ๋๋ ๋ฐ๋์ ๋์ ์๋๋๋ก ์ฝ๋๊ฐ ๋์ํ์ง ์๋๋ค.
function handleBtnActivateById(event) {
setIdValue(event.target.value);
console.log(idValue);
isIdVaild = idValue.indexOf('@') !== -1 ? true : false;
handleBtnActivate(event);
}
์์ ์ฌ์ง์ฒ๋ผ, ์ ๋ ฅ์ฐฝ์ ์ ๋ ฅ๋ ๊ฐ์ด (์ฝ์์ฐฝ์์) ํ ๊ธ์์ฉ ๋ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๐ก ๋ฌธ์ ํด๊ฒฐ ๋ฐ ๊ณผ์
๊ตฌ๊ธ๋ง์ ํตํด ์์๋ณด๋, setState์ Batch Update๋ผ๋ ๋น๋๊ธฐ์ ํน์ฑ์ผ๋ก ์ธํด ์ด๋ฐ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ ๊ฒ์์ ์ ์ ์์๋ค.
React๋ setState๊ฐ ์ฐ์์ผ๋ก ํธ์ถ๋๋ค๋ฉด Batch Update๋ฅผ ํตํค ์ด๋ฅผ ํ ๋ฒ์ ๋ ๋๋งํ๋ค. ์ฆ, useState๋ ๋๊ธฐ์ ์ด ์๋ ๋น๋๊ธฐ์ ์ผ๋ก ์๋ํ๋ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ๋์ํ๋ ์ด์ ๋, ๋ถํ์ํ ๋๋๋ง์ ๋ฐฉ์งํ์ฌ ์ฑ๋ฅ์ ํฅ์ํ๊ธฐ ์ํจ๋ ์๊ณ , ๋ง์ผ useState๊ฐ ๋๊ธฐ์ ์ผ๋ก ๋์ ์ ๋๋ฒ๊น ์ ํฐ ์ด๋ ค์์ด ์ผ๊ธฐ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด๋ฌํ ํน์ฑ์ผ๋ก ์ธํด ์๊ธด ์ด๋ฒ ๋ฌธ์ ๋, ์ฐพ์๋ณด๋ ๋๋ต ๋ ๊ฐ์ง์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์๊ฐ๋์๋๋ฐ
- ํ๋๋ setState์ ์ธ์๋ก, ์ ๋ฐ์ดํธ ํ ๊ฐ์ด ์๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฃผ๋ ๋ฐฉ๋ฒ์ด์๊ณ
- ๋ค๋ฅธ ํ๋๋ useEffect๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด์๋ค.
useEffect๋ ์์ง ํ์ตํ์ง ์์ ๋ด์ฉ์ด๊ธฐ์, ์ฐ์ setState์ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ธ์๋ก ์ฃผ๋ ๋ฐฉ๋ฒ์ ์ฐ์ ์๋ํด๋ณด์๋ค.
let isIdVaild = false;
let isPwVaild = false;
let isAllVaild = false;
export default function Login() {
const navigate = useNavigate();
const [idValue, setIdValue] = useState('');
const [pwValue, setPwValue] = useState('');
function handleBtnActivate() {
if (isIdVaild && isPwVaild) {
isAllVaild = true;
} else {
isAllVaild = false;
}
}
function handleBtnClick() {
if (isAllVaild) {
navigate('/leesangyoon/main');
}
}
function handleBtnActivateById(event) {
setIdValue(idValue => {
idValue = event.target.value;
return idValue;
}); // ์์ ๋ถ๋ถ
isIdVaild = idValue.indexOf('@') !== -1 ? true : false;
handleBtnActivate();
}
function handleBtnActivateByPw(event) {
setPwValue(pwValue => {
pwValue = event.target.value;
return pwValue;
}); // ์์ ๋ถ๋ถ
isPwVaild = pwValue.length >= 5 ? true : false;
handleBtnActivate();
}
return (
<div className="container">
<div className="first-box">
<header className="first-box__title">westagram</header>
<section className="first-box__login-form">
<input
id="input-id"
className="first-box__login-form__input"
type="text"
placeholder="์ ํ๋ฒํธ, ์ฌ์ฉ์ ์ด๋ฆ ๋๋ ์ด๋ฉ์ผ"
onInput={event => handleBtnActivateById(event)}
/>
<input
id="input-pw"
className="first-box__login-form__input"
type="text"
placeholder="๋น๋ฐ๋ฒํธ"
onInput={event => handleBtnActivateByPw(event)}
/>
<button
className={`first-box__login-form__btn ${
isAllVaild ? '' : 'opacity'
}`}
onClick={() => handleBtnClick()}
>
๋ก๊ทธ์ธ
</button>
</section>
<footer className="first-box__forget-pw">
<a href="#">๋น๋ฐ๋ฒํธ๋ฅผ ์์ผ์
จ๋์?</a>
</footer>
</div>
...
</div>
)
ํ์ง๋ง ์ฌ์ ํ ์ ๋ ฅ์ฐฝ์ ์ ๋ ฅ๋ ๊ฐ์ด (์ฝ์์ฐฝ์์) ํ ๊ธ์์ฉ ๋ ์ถ๋ ฅ๋๋ ํ์์ด ์ฌ๋ผ์ง์ง ์์๋ค.
๊ทธ๋์ useEffect๋ฅผ ํ์ตํ๊ณ ๋ ํ ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์๋ค.
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './Login.scss';
export default function Login() {
const navigate = useNavigate();
const [idValue, setIdValue] = useState('');
const [pwValue, setPwValue] = useState('');
const [isAllVaild, setIsAllValid] = useState(false);
useEffect(() => {
if (idValue.indexOf('@') !== -1 && pwValue.length >= 5) {
setIsAllValid(true);
} else {
setIsAllValid(false);
}
}, [idValue, pwValue]);
function handleBtnClick() {
if (isAllVaild) {
navigate('/leesangyoon/main');
}
}
function handleBtnActivateById(event) {
setIdValue(idValue => {
idValue = event.target.value;
return idValue;
});
}
function handleBtnActivateByPw(event) {
setPwValue(pwValue => {
pwValue = event.target.value;
return pwValue;
});
}
return (
<div className="container">
<div className="first-box">
<header className="first-box__title">westagram</header>
<section className="first-box__login-form">
<input
id="input-id"
className="first-box__login-form__input"
type="text"
placeholder="์ ํ๋ฒํธ, ์ฌ์ฉ์ ์ด๋ฆ ๋๋ ์ด๋ฉ์ผ"
onInput={event => handleBtnActivateById(event)}
/>
<input
id="input-pw"
className="first-box__login-form__input"
type="text"
placeholder="๋น๋ฐ๋ฒํธ"
onInput={event => handleBtnActivateByPw(event)}
/>
<button
className={`first-box__login-form__btn ${
isAllVaild ? '' : 'opacity'
}`}
onClick={() => handleBtnClick()}
>
๋ก๊ทธ์ธ
</button>
</section>
<footer className="first-box__forget-pw">
<a href="#">๋น๋ฐ๋ฒํธ๋ฅผ ์์ผ์
จ๋์?</a>
</footer>
</div>
...
</div>
);
}
useEffect์ ์์กด์ฑ ๋ฐฐ์ด ๋ด๋ถ์ ์์ฑํ ๋ณ์๊ฐ์ด ๋ณํ ๋๋ง๋ค useEffect์ ์ฒซ ๋ฒ์งธ ์ธ์์ธ ์ฝ๋ฐฑ ํจ์๊ฐ ์คํ๋๋ค. ๋ฐ๋ผ์ ์ํ๊ฐ์ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฃ๊ณ , ๊ทธ ๊ฐ์ ์ด์ฉํ ํน์ ๋ก์ง์ ์ฝ๋ฐฑ ํจ์์ ์์ฑํ๋ฉด, ์ํ๊ฐ์ด ๋ฐ๋๊ณ ๋ ์ดํ์ ๊ทธ ๋ก์ง์ด ์ํ๋๋ฏ๋ก ์์ ์ ์๋๋๋ก ์ฝ๋๋ฅผ ๋์์ํฌ ์ ์๋ค. (์ฐจํ useEffect์ ๋ํด ๋ ๊น์ ํ์ต์ ์งํํ๊ณ ๋์ ์ด ๋ฌธ์ ๋ฅผ ๋ค์ ์ดํด๋ณด๋๋ก ํ์)
๐ฌ ๋๋ ์
setState์ ๋น๋๊ธฐ์ ํน์ฑ์ผ๋ก ์ธํด ์๊ธฐ๋ ๋ฒ๊ทธ๋ ๋ ์ด์ธ์๋ React๋ฅผ ์ฐ๋ ๋ง์ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ๋ถ๋ค์ด ํ ๋ฒ์ฏค ์ ํด๋ดค์ ๋ฌธ์ ๋ ์๊ฐ์ด ๋ ๋ค. ์ค์ ๋ก ๋ด๊ฐ ์ด ๋ฌธ์ ๋ฅผ ๋ง์ฃผํ ์ดํ ๋ถํธ์บ ํ์์ ๊ฐ์ด ๊ณต๋ถํ๋ ๋๊ธฐ ๋ถ๋ค ์ฌ๋ฟ์ด ๊ฐ์ ๋ฌธ์ ๋ก ์ ์๊ฒ ์ง๋ฌธ์ ํด์ฃผ์ จ๋ค. ๊ทธ ๋๋ง๋ค ๋์๋๋ฆฌ๋ฉด์, ์ ๋ฒ์ ์ด ๋ฌธ์ ๋ฅผ ์ ๋๋ก ํด๊ฒฐํ์ง ์๊ณ ๋์ถฉ ๋์ด๊ฐ๋ ๋ด ํ๋์ ๋ํ ํํ๊ฐ ๋ง์ด ๋ค์๋ค. (๋น๋ก ์๊ฐ์ด ๋ถ์กฑํด์.. ๋ผ๋ ํ๊ณ๊ฐ ์๊ธด ํ์ง๋ง..)
์์ผ๋ก๋ ๋ชจ๋ฅด๋ ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ์ด๋ฅผ ๊ผญ ์ ๋๋ก ํด๊ฒฐํ๊ณ , ๋ฌธ์ ์ ์์ธ๊ณผ ํด๊ฒฐ๊ณผ์ ์ ์ ๋๋ก ์๊ณ ๊ฐ๋๋ก ํด์ผ๊ฒ ๋ค.