React/React

useState 바로 뒤에 console.log 를 했더니 이전 값이 나온다.(혹은 비어있다)

onurmind38 2023. 3. 7. 17:12

📌 useState 바로 뒤에 console.log 를 했더니 이전 값이 나온다.(혹은 비어있다) 라는 문제가 생겼다.

 

코드를 먼저보자

import { useEffect, useState } from "react";

function Todolist() {

  const [todo, setTodo] = useState<string>("");

  const todoHandler = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const todoData = new FormData(e.currentTarget);
    const newTodo = todoData.get("todo") as string;
    setTodo(newTodo);
    console.log(todo) //비어있는 값이 출력된다.
    e.currentTarget.reset();
};

useEffect(()=>console.log(todo) , [todo])

  return (
    <>
      <div>
        <form onSubmit={todoHandler}>
          <input type="text" name="todo" placeholder="write to do" />
          <button>Add</button>
        </form>
        {todo}
      </div>
    </>
  );
}

export default Todolist;

todoHandler 에서 setTodo 를 세팅하고 console.log(todo)를 호출하였는데 

세팅한 값이 나오지 않고 처음엔 비어있고 그다음부터는 이전 값이 출력된다.

 

이유는 바로  useState 는 비동기 이기 때문이다. 

즉 setTodo는 잠시 미뤄두고 console.log 를 먼저 실행해버리기 때문에 이전값이 출력되어 버리는 것이다.

 

📌그렇다면 setTimeout 을 통해  console.log 를 나중에 실행하면 값이 할당된 상태에서 출력되지 않을까?

그래서 console.log 대신 아래 코드로 5초뒤에 출력되게 해보았다.

setTimeout(()=>console.log(todo) , 5000)

그러나 문제는 여전히 계속되었다. 이유는 다음과 같다.

 

setTimeout 을 통해 5초 뒤 호출되는 것은 맞으나 호출시점에서 변수의 값을 가져가는 것이 아니다.

이미 함수가 명령된 상태에서 todo의 값을 가져간 뒤 단순히 5초뒤 실행된것이기 때문이다.

 

📌 해결방법은 useEffect(()=>console.log(todo) , [todo])

이미 가장 처음 전체 코드에서도 보았듯

useEffect 를 통해 todo가 변했을때 console.log 가 실행될 수 있도록 하는 것이 해결책이다.