โ—ผ FrontEnd/ReactJS

[ReactJS] setState์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋กœ ์ธํ•œ ๋ฒ„๊ทธ ํ•ด๊ฒฐํ•˜๊ธฐ

SangYoonLee (SYL) 2022. 11. 4. 22:45
๋ฐ˜์‘ํ˜•

๐Ÿšจ ๋ฌธ์ œ ์ƒํ™ฉ

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๋ฅผ ์“ฐ๋Š” ๋งŽ์€ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ๋ถ„๋“ค์ด ํ•œ ๋ฒˆ์ฏค ์ ‘ํ•ด๋ดค์„ ๋ฌธ์ œ๋ž€ ์ƒ๊ฐ์ด ๋“ ๋‹ค. ์‹ค์ œ๋กœ ๋‚ด๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ๋งˆ์ฃผํ•œ ์ดํ›„ ๋ถ€ํŠธ์บ ํ”„์—์„œ ๊ฐ™์ด ๊ณต๋ถ€ํ•˜๋Š” ๋™๊ธฐ ๋ถ„๋“ค ์—ฌ๋Ÿฟ์ด ๊ฐ™์€ ๋ฌธ์ œ๋กœ ์ €์—๊ฒŒ ์งˆ๋ฌธ์„ ํ•ด์ฃผ์…จ๋‹ค. ๊ทธ ๋•Œ๋งˆ๋‹ค ๋„์™€๋“œ๋ฆฌ๋ฉด์„œ, ์ €๋ฒˆ์— ์ด ๋ฌธ์ œ๋ฅผ ์ œ๋Œ€๋กœ ํ•ด๊ฒฐํ•˜์ง€ ์•Š๊ณ  ๋Œ€์ถฉ ๋„˜์–ด๊ฐ”๋˜ ๋‚ด ํ–‰๋™์— ๋Œ€ํ•œ ํ›„ํšŒ๊ฐ€ ๋งŽ์ด ๋“ค์—ˆ๋‹ค. (๋น„๋ก ์‹œ๊ฐ„์ด ๋ถ€์กฑํ•ด์„œ.. ๋ผ๋Š” ํ•‘๊ณ„๊ฐ€ ์žˆ๊ธด ํ•˜์ง€๋งŒ..)

์•ž์œผ๋กœ๋Š” ๋ชจ๋ฅด๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ์ด๋ฅผ ๊ผญ ์ œ๋Œ€๋กœ ํ•ด๊ฒฐํ•˜๊ณ , ๋ฌธ์ œ์˜ ์›์ธ๊ณผ ํ•ด๊ฒฐ๊ณผ์ •์„ ์ œ๋Œ€๋กœ ์•Œ๊ณ  ๊ฐ€๋„๋ก ํ•ด์•ผ๊ฒ ๋‹ค.

 

๋ฐ˜์‘ํ˜•