해결된 질문
작성
·
476
·
수정됨
0
안녕하세요.
사용자 입력 처리하기 강의 관련 질문입니다.
input 태그를 통해 사용자 입력을 받고, 상태 관리하면, 상태에 사용자의 입력이 반영되는 게 한 단계씩 늦는 것 같습니다. (그 이유가 useState가 비동기적으로 처리된다고 들은적이 있는 것 같은데, 정확히 이해가 가지 않아서 질문드립니다.)
아래 코드의 handleOnChange함수에서,
import { useState } from 'react';
const DiaryEditor = () => {
const [input, setInput] = useState({
author: '',
content: '',
emotion: 1,
});
const handleOnChange = (e) => {
console.log(e.target.name);
console.log(e.target.value);
setInput({ ...input, [e.target.name]: e.target.value });
console.log(input);
};
const handleSubmit = () => {
console.log(input);
alert('오늘의 일기가 저장되었습니다!');
};
return (
<div className='DiaryEditor'>
<h2>오늘의 일기</h2>
<div>
<input name='author' value={input.author} onChange={handleOnChange} />
<p>{input.author}</p>
</div>
<div>
<textarea
value={input.content}
name='content'
onChange={handleOnChange}
/>
<p>{input.content}</p>
</div>
<div>
<span>감정 지수 : </span>
<select
onChange={handleOnChange}
name='emotion'
value={input.emotion}
>
<option value={1}>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option value={5}>5</option>
</select>
</div>
<div>
<button onClick={handleSubmit}>저장하기</button>
</div>
</div>
);
};
export default DiaryEditor;
state가 곧바로 변하지 않는거면, 이 인풋의 value 속성은 무용지물인 것 아닌가라는 생각이 들어 질문드립니다.
<select
onChange={handleOnChange}
name='emotion'
value={input.emotion}
>
답변 1
0
안녕하세요 이정환입니다.
우선 useState의 setState가 비동기적으로 동작하는 이유는 컴포넌트가 렌더링 하는 UI를 변경을 반영한 상태로 다시 렌더링해야 하기 때문입니다.
더 구체적으로 말씀드리자면 setState가 호출되었을 때 리액트가 내부적으로 컴포넌트를 다시 호출하여 변경된 State 값이 적용된 UI를 렌더링 하도록 해 화면을 업데이트 하기 위함입니다.
따라서 다음과 같은 함수가 호출되면 React는 함수를 끝 마친 이후에 해당 컴포넌트를 다시 호출해 리렌더를 발생 시키기 때문에 console.log(input) 까지는 변경된 State의 값이 즉시 반영되지 않는 것 입니다.
const handleOnChange = (e) => {
console.log(e.target.name);
console.log(e.target.value);
setInput({ ...input, [e.target.name]: e.target.value });
console.log(input);
};
중요한 것은 컴포넌트 역할을 하는 함수 자체가 다시 호출되어야 하기 때문에 이렇게 동작한다고 이해하시면 될 것 같습니다!
<select> 태그의 value 속성을 주는 이유는 앞서 말씀 드린 대로 State가 변경되어 컴포넌트 역할을 하는 함수가 다시 호출되었을 때 변경된 State를 반영한 UI를 렌더링 시키기 위함 입니다.
구체적으로 순서를 나열해보자면 이렇습니다.
초기 상태 렌더링
setState 호출로 인해 상태 업데이트
React가 내부적으로 상태가 변경된 컴포넌트 재 호출
재 호출된 컴포넌트는 변경된 State를 반영한 UI를 다시 리턴
추가로 useState의 초기값으로 ""을 넣어주는 이유는 다음과 같은 경우 오류가 발생할 수 있기 때문에 그렇습니다.
const App() => {
const [text, setText] = useState(); // text 초기값은 undefined
return (
<div>
{text.toUpperCase()}
// undefined is not object 에러 발생
</div>
);
}
자바스크립트에서는 undefined 값을 객체로 착각하고 메서드를 호출하려고 하거나 프로퍼티에 접근하려고 하면 런타임 오류를 발생시킵니다. 따라서 문자열로 예상될 State의 값을 초기화 할 때에는 undefined으로 초기화 시키는 것 보다 ""을 통해 빈 문자열로 초기화 시켜두는 것이 훨씬 안전합니다.