새로운 게시글을 작성할 수 있는 폼이 있다고 가정하자. 그렇다면 사용자가 브라우저 화면에 입력하는 값들을 우리의 웹애플리케이션이 받아와서 state에 저장하고 화면에 보여주고 백엔드 쪽 데이터베이스에 update를 해줘야 할 것이다.
const Create = () => {
return (
<div className="create">
<h2>Add a New Blog</h2>
<form>
<label>Blog title:</label>
<input type="text" required />
<label>Blog body:</label>
<textarea required></textarea>
<label>Blog author:</label>
<select>
<option value="morello">morello</option>
<option value="donglee">donglee</option>
</select>
<button>Add blog</button>
</form>
</div>
);
};
위와 같은 새로운 게시글을 만드는 Create 컴포넌트가 있고 그 모습은 아래 이미지와 같다.
그런데 사용자가 입력하는 Input들을 컴포넌트의 state에 저장해서 활용하고 싶을 수가 있다. 그래서 위 create 컴포넌트 상단에 const [title, setTitle] = useState("hello")
이런 식으로 state를 추가한 후에 <input type="text" required value={title}/>
이렇게 하면 될 것 처럼 보인다. 하지만 이렇게 수정을 했을 때 화면에서 Blog title: 부분에 우리가 state의 초기값으로 설정한 hello가 보이지만 막상 그 input창에 어떤 값을 입력하려고 하면 hello 문자열이 바뀌지 않는다. 그리고 콘솔창에는 Warning: You provided a 'value' prop to a form field without an 'onChange' handler. This will render a read-only field. If the field should be mutable use 'defaultValue'. Otherwise, set either 'onChange' or 'readOnly'.
와 같은 에러메세지를 받게 된다.
에러메세지는 form field에 value prop을 넣었는데 onChange 가 없기 때문에 read-only 를 렌더링 할 것이라고 한다. 그렇기 때문에 수정이 불가했던 것이다.
그래서 아래와 같이 바꾼다면 우리가 의도한대로 state에 사용자가 입력한 값을 저장하고 그 값을 사용자한테 그대로 보여줄 수 있을 것이다.
const Create = () => {
const [title, setTitle] = useState("");
const [body, setBody] = useState("");
const [author, setAuthor] = useState("morello");
return (
<div className="create">
<h2>Add a New Blog</h2>
<form>
<label>Blog title:</label>
<input
type="text"
required
value={title}
onChange={e => setTitle(e.target.value)}
/>
//onChange 추가
...
</div>
);
};
위 코드와 같이 onChange
를 추가하고 이벤트 객체의 value값을 참조해서 state를 setTitle
로 업데이트해준다. 그리고 input 태그의 value prop을 업데이트된 state인 {title}
로 해준다면 의도한대로 구현이 가능하다.