HTML에서 input
, textarea
, select
같은 폼 엘리먼트는 일반적으로 사용자의 입력이 변경되는 걸 감지하고 알아서 데이터를 저장하고 수정함. 폼을 제출하면 새로운 페이지로 넘어가 주는 것이 기본 동작이지만, Javascript를 이용해 사용자 입력을 처리하고 제출하는 과정을 통제하는게 더 편리함. React에서는 state를 이용해 폼 엘리먼트의 기존 기능을 구현할 수 있음. 이를 위한 기술이 제어 컴포넌트
제어 컴포넌트를 사용하면 Input의 값은 항상 React state에 의해 결정됨. 기본 동작 방식을 사용하는게 아니라 코드를 더 작성해주어야 하는 기술이지만, 다른 UI 엘리먼트에 입력값을 전달하거나 다른 이벤트 핸들러에서 값을 재설정하는 등 추가적인 작업을 하기 용이함.
기존의 Textarea는 태그 사이에 값을 넣어 기본값을 설정하는 방식
<textarea>
this is basic example
</textarea>
리액트에서는 value값과 state를 이용해 값을 저장하고 불러온다.
import { useState } from "react"
export default function TextArea() {
const [textInput, setTextInput] = useState("text me")
const handleChange = (e) => {
setTextInput(e.target.value)
}
const handleSubmit = (e) => {
alert("submit " + textInput)
e.preventDefault()
}
return (
<form onSubmit={handleSubmit}>
<label>
Textbox :<textarea value={textInput} onChange={handleChange}></textarea>
</label>
<button type="submit">submit</button>
</form>
)
}
HTML에서 사용되던 기존의 select는 selected옵션을 사용해 초기값과 선택되는 값을 지정해줌
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
리액트에서는 selected를 사용하지 않고 value를 이용해 select 박스의 값을 출력해서 보여줌
import { useState } from "react"
export default function Select() {
const [select, setSelect] = useState("coconut")
const handleChange = (e) => {
setSelect(e.target.value)
}
const handleSubmit = (e) => {
alert("your favorite fruits is " + select)
e.preventDefault()
}
return (
<form onSubmit={handleSubmit}>
<label>
Pick your favorite flavor:
<select value={select} onChange={handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
)
}
select 태그에 여러 값을 허용한다면 value attribute 에 배열을 넣으면 됨.
<select multiple={true} value={['B', 'C']}>
<input type = file/>
html에서는 사용자의 저장소에서 서버로 업로드 하거나 javascript로 조작할 수 있지만, react에서는 읽기 전용으로 프로그래밍적으로 값을 설정할 수 없고, 사용자만 값을 설정할 수 있기 때문에 비제어 컴포넌트
로 사용됨.
import React from "react"
export default function FileInput() {
const fileInput = React.createRef()
const handleSubmit = (event) => {
event.preventDefault()
alert(`selected file - ${fileInput.current.files[0].name}`)
}
return (
<form onSubmit={handleSubmit}>
<label htmlFor="file">file : </label>
<input type="file" id="file" ref={fileInput} />
<br />
<button>submit</button>
</form>
)
}
제어 컴포넌트
: form 데이터에 대한 처리가 React내부에서 이뤄짐
비제어 컴포넌트
: form 데이터에 대한 처리가 DOM자체에서 이뤄짐
DOM에서 이뤄지기 때문에 DOM을 가져오기 위해 ref를 사용해야함. 가급적이면 제어 컴포넌트를 사용하는 것이 권장됨.
React에서는 보통 value를 이용해 DOM의 value를 대체함.
<select value={select} onChange={handleChange}>
하지만 비제어 컴포넌트에서는 React 초깃값을 지정하는 것만 권장됨.
value 대신 defaultvalue
를 사용해 어트리뷰트를 변경
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob"
type="text"
ref={this.input} />
</label>
<input type="submit" value="Submit" />
</form>