<input>
<input> ๋ธ๋ผ์ฐ์ ๋ด์ฅ ์ปดํฌ๋ํธ ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ์ข
๋ฅ์ form input ์ ๋ ๋๋ง ํ ์ ์์ต๋๋ค.
<input />- ๋ ํผ๋ฐ์ค
- ์ฌ์ฉ๋ฒ
- ๋ฌธ์ ํด๊ฒฐ
- ํ ์คํธ input์ ํ์ดํ์ ํด๋ ์ ๋ฐ์ดํธ๋์ง ์์ต๋๋ค
- ์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํด๋ ์ ๋ฐ์ดํธ๋์ง ์์ต๋๋ค
- ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค ์ ๋ ฅ ์ปค์๊ฐ input์ ์ฒ์์ผ๋ก ๋์๊ฐ๋๋ค
- ๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ๋ฉ๋๋ค. โA component is changing an uncontrolled input to be controlled(์ปดํฌ๋ํธ๊ฐ ์ ์ด๋์ง ์๋ input์ ์ ์ด ์ํ๋ก ๋ณ๊ฒฝํฉ๋๋ค)โ
๋ ํผ๋ฐ์ค
<input>
input ์ ํ์ํ๋ ค๋ฉด, <input> ๋ธ๋ผ์ฐ์ ๋ด์ฅ ์ปดํฌ๋ํธ ๋ฅผ ๋ ๋๋ง ํ์ธ์.
<input name="myInput" />์๋์ ๋ ๋ง์ ์์๊ฐ ์์ต๋๋ค.
Props
<input> ์ ์ผ๋ฐ์ ์ธ ์๋ฆฌ๋จผํธ props ๋ฅผ ์ง์ํฉ๋๋ค.
input์ ์ ์ดํ๊ธฐ ์ํด์ ์๋ props ๋ค ์ค์ ํ๋๋ฅผ ์ ๋ฌํ์ธ์.
checked: ๋ถ๋ฆฌ์ธ ํ์ . ์ฒดํฌ๋ฐ์ค input ๋๋ ๋ผ๋์ค ๋ฒํผ์์ ์ ํ ์ฌ๋ถ๋ฅผ ์ ์ดํฉ๋๋ค.value: ๋ฌธ์์ด ํ์ . ํ ์คํธ input์ ๊ฒฝ์ฐ ํ ์คํธ๋ฅผ ์ ์ดํฉ๋๋ค. (๋ผ๋์ค ๋ฒํผ์ ๊ฒฝ์ฐ ํผ ๋ฐ์ดํฐ๋ฅผ ์ง์ ํฉ๋๋ค.)
๋ ์ค ํ๋๋ฅผ ์ ๋ฌํ ๋๋ ๋ฐ๋์ ์ ๋ฌ๋ ๊ฐ์ ์
๋ฐ์ดํธํ๋ onChange ํธ๋ค๋ฌ๋ ํจ๊ป ์ ๋ฌํด์ผ ํฉ๋๋ค.
๋ค์์ <input> props ๋ค์ ์ ์ด๋์ง ์๋ input๋ค์๋ง ์ ์ฉ๋ฉ๋๋ค.
defaultChecked: ๋ถ๋ฆฌ์ธ ํ์ .type="checkbox"์type="radio"input์ ๋ํ ์ด๊ธฐ๊ฐ ์ ์ง์ ํฉ๋๋ค.defaultValue: ๋ฌธ์์ด ํ์ . ํ ์คํธ input์ ๋ํ ์ด๊ธฐ๊ฐ ์ ์ง์ ํฉ๋๋ค.
๋ค์์ <input> props ๋ค์ ์ ์ด๋์ง ์๋ input๊ณผ ์ ์ด๋๋ input ๋ชจ๋์ ์ ์ฉ๋ฉ๋๋ค.
accept: ๋ฌธ์์ด ํ์ .type="file"input์์ ํ์ฉํ ํ์ผ ํ์์ ์ง์ ํฉ๋๋ค.alt: ๋ฌธ์์ด ํ์ .type="image"input์์ ๋์ฒด ์ด๋ฏธ์ง ํ ์คํธ๋ฅผ ์ง์ ํฉ๋๋ค.capture: ๋ฌธ์์ด ํ์ .type="file"input์ผ๋ก ์บก์ฒํ ๋ฏธ๋์ด(๋ง์ดํฌ, ๋น๋์ค ๋๋ ์นด๋ฉ๋ผ)๋ฅผ ์ง์ ํฉ๋๋ค.autoComplete: ๋ฌธ์์ด ํ์ . ์๋ ์์ฑ ๋์๋ค ์ค ๊ฐ๋ฅํ ํ๋๋ฅผ ์ง์ ํฉ๋๋ค.autoFocus: ๋ถ๋ฆฌ์ธ ํ์ .true์ผ ๊ฒฝ์ฐ React๋ ๋ง์ดํธ ์ ์๋ฆฌ๋จผํธ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถฅ๋๋ค.dirname: ๋ฌธ์์ด ํ์ . ์๋ฆฌ๋จผํธ ๋ฐฉํฅ์ฑ์ ๋ํ ํผ ํ๋ ์ด๋ฆ์ ์ง์ ํฉ๋๋ค.disabled: ๋ถ๋ฆฌ์ธ ํ์ .true์ผ ๊ฒฝ์ฐ, input์ ์ํธ์์ฉ์ด ๋ถ๊ฐ๋ฅํด์ง๋ฉฐ ํ๋ฆฟํ๊ฒ ๋ณด์ ๋๋ค.children:<input>์ ์์์ ๋ฐ์ง ์์ต๋๋ค.form: ๋ฌธ์์ด ํ์ . input์ด ์ํ๋<form>์id๋ฅผ ์ง์ ํฉ๋๋ค. ์๋ต ์ ๊ฐ์ฅ ๊ฐ๊น์ด ๋ถ๋ชจ ํผ์ผ๋ก ์ค์ ๋ฉ๋๋ค.formAction: ๋ฌธ์์ด ํ์ .type="submit"๊ณผtype="image"์ ๋ถ๋ชจ<form action>์ ๋ฎ์ด์๋๋ค.formEnctype: ๋ฌธ์์ด ํ์ .type="submit"๊ณผtype="image"์ ๋ถ๋ชจ<form enctype>์ ๋ฎ์ด์๋๋ค.formMethod: ๋ฌธ์์ด ํ์ .type="submit"๊ณผtype="image"์ ๋ถ๋ชจ<form method>๋ฅผ ๋ฎ์ด์๋๋ค.formNoValidate: ๋ฌธ์์ด ํ์ .type="submit"๊ณผtype="image"์ ๋ถ๋ชจ<form noValidate>๋ฅผ ๋ฎ์ด์๋๋ค.formTarget: ๋ฌธ์์ด ํ์ .<form target>fortype="submit"๊ณผtype="image"์ ๋ถ๋ชจ<form target>์ ๋ฎ์ด์๋๋ค.height: ๋ฌธ์์ด ํ์ .type="image"์ ์ด๋ฏธ์ง ๋์ด๋ฅผ ์ง์ ํฉ๋๋ค.list: ๋ฌธ์์ด ํ์ .<datalist>์id๋ฅผ ์๋ ์์ฑ ์ต์ ๋ค๋ก ์ง์ ํฉ๋๋ค.max: ์ซ์ ํ์ . ์ซ์ ์ ๋ ์ง input๋ค์ ์ต๋๊ฐ์ ์ง์ ํฉ๋๋ค.maxLength: ์ซ์ ํ์ . ํ ์คํธ์ ๋ค๋ฅธ input๋ค์ ์ต๋ ๊ธธ์ด๋ฅผ ์ง์ ํฉ๋๋ค.min: ์ซ์ ํ์ . ์ซ์ ์ ๋ ์ง input๋ค์ ์ต์๊ฐ์ ์ง์ ํฉ๋๋ค.minLength: ์ซ์ ํ์ . ํ ์คํธ์ ๋ค๋ฅธ input๋ค์ ์ต์ ๊ธธ์ด๋ฅผ ์ง์ ํฉ๋๋ค.multiple: ๋ถ๋ฆฌ์ธ ํ์ .type="file"๊ณผtype="email"์ ๋ํด ์ฌ๋ฌ ๊ฐ์ ํ์ฉํ ์ง ์ฌ๋ถ๋ฅผ ์ง์ ํฉ๋๋ค.name: ๋ฌธ์์ด ํ์ . ํผ๊ณผ ์ ์ถ ๋๋ input์ ์ด๋ฆ์ ์ง์ ํฉ๋๋ค.onChange:์ด๋ฒคํธํธ๋ค๋ฌ ํจ์. ์ ์ด๋๋ input ํ์ ์์๋ก ๊ฐ๋ น ์ฌ์ฉ์๊ฐ ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค ์คํ๋๋ ๋ฐฉ์์ผ๋ก input ๊ฐ์ ๋ณ๊ฒฝํ๋ ์ฆ์ ์คํ๋๋ฉฐ ๋ธ๋ผ์ฐ์ input์ด๋ฒคํธ์ฒ๋ผ ๋์ํฉ๋๋ค.onChangeCapture: ์บก์ฒ ๋จ๊ณ์์ ์คํ๋๋onChangeonInput:์ด๋ฒคํธํธ๋ค๋ฌ ํจ์. ์ฌ์ฉ์๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ๋ ์ฆ์ ์คํ๋ฉ๋๋ค. ์ง๊ธ๊น์ง์ ์ฉ๋ฒ์ ๋น์ถฐ๋ดค์ ๋ React์์๋ ์ ์ฌํ๊ฒ ๋์ํ๋onChange๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ด์ต์ ์ ๋๋ค.onInputCapture: ์บก์ฒ ๋จ๊ณ์์ ์คํ๋๋onInputonInvalid:์ด๋ฒคํธํธ๋ค๋ฌ ํจ์. ํผ ์ ์ถ ์ input์ด ์ ํจํ์ง ์์ ๊ฒฝ์ฐ ์คํ๋๋ฉฐinvalid๋ด์ฅ ์ด๋ฒคํธ์ ๋ฌ๋ฆฌ ReactonInvalid์ด๋ฒคํธ๋ ๋ฒ๋ธ๋ง๋ฉ๋๋ค.onInvalidCapture: ์บก์ฒ ๋จ๊ณ์์ ์คํ๋๋onInvalidonSelect:์ด๋ฒคํธํธ๋ค๋ฌ ํจ์.<input>๋ด๋ถ์ ์ ํ ์ฌํญ์ด ๋ณ๊ฒฝ๋ ํ ์คํ๋ฉ๋๋ค. React๋onSelect์ด๋ฒคํธ๋ฅผ ํ์ฅํ์ฌ ์ ํ ์ฌํญ์ด ๋น๊ฑฐ๋ ํธ์ง ์ ์ ํ ์ฌํญ์ ์ํฅ์ ๋ผ์น๊ฒ ๋ ๋๋ ์คํ๋ฉ๋๋ค.onSelectCapture: ์บก์ฒ ๋จ๊ณ์์ ์คํ๋๋onSelectpattern: ๋ฌธ์์ด ํ์ .value๊ฐ ์ผ์นํด์ผ ํ๋ ํจํด์ ์ง์ ํฉ๋๋ค.placeholder: ๋ฌธ์์ด ํ์ . input ๊ฐ์ด ๋น์์ ๋ ํ๋ฆฐ ์์ผ๋ก ํ์๋ฉ๋๋ค.readOnly: ๋ถ๋ฆฌ์ธ ํ์ .true์ผ ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ input์ ํธ์งํ ์ ์์ต๋๋ค.required: ๋ถ๋ฆฌ์ธ ํ์ .true์ผ ๊ฒฝ์ฐ ํผ์ด ์ ์ถํ ๊ฐ์ ๋ฐ๋์ ์ ๊ณตํด์ผ ํฉ๋๋ค.size: ์ซ์ ํ์ . ๋๋น๋ฅผ ์ค์ ํ๋ ๊ฒ๊ณผ ๋น์ทํ์ง๋ง ๋จ์๋ ์ ์ด์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค.src: ๋ฌธ์์ด ํ์ .type="image"input์ ์ด๋ฏธ์ง ์์ค๋ฅผ ์ง์ ํฉ๋๋ค.step: ์์ ๋๋'any'๋ฌธ์์ด. ์ ํจํ ๊ฐ ์ฌ์ด์ ๊ฐ๊ฒฉ์ ์ง์ ํฉ๋๋ค.type: ๋ฌธ์์ด ํ์ . input types ์ค์ ํ๋width: ๋ฌธ์์ด ํ์ .type="image"input์ ์ด๋ฏธ์ง ๋๋น๋ฅผ ์ง์ ํฉ๋๋ค.
๊ฒฝ๊ณ
- ์ฒดํฌ๋ฐ์ค์๋
value(๋๋defaultValue)๊ฐ ์๋checked(๋๋defaultChecked)๊ฐ ํ์ํฉ๋๋ค. - ํ
์คํธ input ์์ญ์ ๋ฌธ์์ด
valueprop์ ๋ฐ์ ๊ฒฝ์ฐ ์ ์ด๋๋ ๊ฒ์ผ๋ก ์ทจ๊ธ๋ฉ๋๋ค. - ์ฒดํฌ๋ฐ์ค ๋๋ ๋ผ๋์ค ๋ฒํผ์ด ๋ถ๋ฆฌ์ธ
checkedprop์ ๋ฐ์ ๊ฒฝ์ฐ ์ ์ด๋๋ ๊ฒ์ผ๋ก ์ทจ๊ธ๋ฉ๋๋ค. - input์ ์ ์ด๋๋ฉด์ ๋์์ ๋น์ ์ด๋ ์ ์์ต๋๋ค.
- input์ ์๋ช ์ฃผ๊ธฐ ๋์ ์ ์ด ๋๋ ๋น์ ์ด ์ํ๋ฅผ ์ค๊ฐ ์ ์์ต๋๋ค.
- ์ ์ด๋๋ input์ ๋ชจ๋ ๋ฐฑ์
๊ฐ์ ๋๊ธฐ์ ์ผ๋ก ์
๋ฐ์ดํธํ๋
onChange์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํ์ํฉ๋๋ค.
์ฌ์ฉ๋ฒ
๋ค์ํ ์ ํ์ input ํ์
input์ ํ์ํ๊ธฐ ์ํด <input> ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋ง ํ์ธ์. ๊ธฐ๋ณธ์ ์ผ๋ก ํ
์คํธ input์ด ๋ฉ๋๋ค. ์ฒดํฌ๋ฐ์ค์๋ type="checkbox"๋ฅผ, ๋ผ๋์ค ๋ฒํผ์๋ type="radio" ์ ๋ฌํ๊ฑฐ๋ ๋ค๋ฅธ input ํ์
๋ค ์ค์ ํ๋๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
export default function MyForm() { return ( <> <label> Text input: <input name="myInput" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" /> </label> <hr /> <p> Radio buttons: <label> <input type="radio" name="myRadio" value="option1" /> Option 1 </label> <label> <input type="radio" name="myRadio" value="option2" /> Option 2 </label> <label> <input type="radio" name="myRadio" value="option3" /> Option 3 </label> </p> </> ); }
input์ ๋ผ๋ฒจ ์ ๊ณตํ๊ธฐ
์ผ๋ฐ์ ์ผ๋ก ๋ชจ๋ <input> ์ <label> ํ๊ทธ ์์ ๋๊ฒ ๋๋๋ฐ ์ด๋ ๊ฒ ํ๋ฉด ํด๋น ๋ผ๋ฒจ์ด ํด๋น input๊ณผ ์ฐ๊ด๋จ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ ์ ์์ต๋๋ค. ์ฌ์ฉ์๊ฐ ๋ผ๋ฒจ์ ํด๋ฆญํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ input์ ์๋์ ์ผ๋ก ํฌ์ปค์ค๋ฅผ ๋ง์ถฅ๋๋ค. ์คํฌ๋ฆฐ ๋ฆฌ๋๋ ์ฌ์ฉ์๊ฐ ์ฐ๊ด๋ input์ ํฌ์ปค์ค๋ฅผ ๋ง์ถ ๋ ๋ผ๋ฒจ ์บก์
์ ์ฝ๊ฒ ๋๋ฏ๋ก ์ด ๋ฐฉ์์ ์ ๊ทผ์ฑ์ ์ํด์๋ ํ์์
๋๋ค.
<label> ์์ <input> ์ ๊ฐ์ ์ ์๋ค๋ฉด, <input id> ์ <label htmlFor>์ ๋์ผํ ID๋ฅผ ์ ๋ฌํด์ ์ฐ๊ด์ฑ์ ๋ถ์ฌํ์ธ์. ํ ์ปดํฌ๋ํธ์ ์ฌ๋ฌ ์ธ์คํด์ค ๊ฐ ์ถฉ๋์ ํผํ๋ ค๋ฉด useId๋ก ๊ทธ๋ฌํ ID๋ฅผ ์์ฑํ์ธ์.
import { useId } from 'react'; export default function Form() { const ageInputId = useId(); return ( <> <label> Your first name: <input name="firstName" /> </label> <hr /> <label htmlFor={ageInputId}>Your age:</label> <input id={ageInputId} name="age" type="number" /> </> ); }
input์ ์ด๊น๊ฐ ์ ๊ณตํ๊ธฐ
input์ ์ด๊น๊ฐ์ ์ ํ์ ์ผ๋ก ์ง์ ํ ์ ์์ต๋๋ค. ํ
์คํธ input์ ์ํ defaultValue ๋ฌธ์์ด๋ก ์ ๋ฌํ์ธ์. ๋์ ์ฒดํฌ๋ฐ์ค์ ๋ผ๋์ค ๋ฒํผ์ defaultChecked ๋ถ๋ฆฌ์ธ์ผ๋ก ์ด๊น๊ฐ์ ์ง์ ํด์ผ ํฉ๋๋ค.
export default function MyForm() { return ( <> <label> Text input: <input name="myInput" defaultValue="Some initial value" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} /> </label> <hr /> <p> Radio buttons: <label> <input type="radio" name="myRadio" value="option1" /> Option 1 </label> <label> <input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2 </label> <label> <input type="radio" name="myRadio" value="option3" /> Option 3 </label> </p> </> ); }
ํผ ์ ์ถ ์ input ๊ฐ ์ฝ๊ธฐ
inputs๊ณผ <button type="submit"> ๋ฐ๊นฅ์ <form> ์ผ๋ก ๊ฐ์ธ๋ฉด ๋ฒํผ์ ํด๋ฆญํ์ ๋ <form onSubmit> ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํธ์ถ๋ฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ ํ์ฌ URL์ ํผ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ํ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ฉฐ ์ด๋ฌํ ๋์์ e.preventDefault()๋ฅผ ํธ์ถํ์ฌ ๋ฎ์ด์ธ ์ ์์ต๋๋ค. ํผ ๋ฐ์ดํฐ๋ new FormData(e.target)๋ก ์ฝ์ผ์ธ์.
export default function MyForm() { function handleSubmit(e) { // ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํ์ง ๋ชปํ๋๋ก ๋ฐฉ์งํฉ๋๋ค. e.preventDefault(); // ํผ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ต๋๋ค. const form = e.target; const formData = new FormData(form); // formData๋ฅผ ์ง์ fetch body๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. fetch('/some-api', { method: form.method, body: formData }); // ๋๋ ์์ object๋ก ์์ ํ ์ ์์ต๋๋ค. const formJson = Object.fromEntries(formData.entries()); console.log(formJson); } return ( <form method="post" onSubmit={handleSubmit}> <label> Text input: <input name="myInput" defaultValue="Some initial value" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} /> </label> <hr /> <p> Radio buttons: <label><input type="radio" name="myRadio" value="option1" /> Option 1</label> <label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Option 2</label> <label><input type="radio" name="myRadio" value="option3" /> Option 3</label> </p> <hr /> <button type="reset">Reset form</button> <button type="submit">Submit form</button> </form> ); }
state ๋ณ์๋ก input ์ ์ดํ๊ธฐ
<input /> ๊ณผ ๊ฐ์ input์ ์ ์ด๋์ง ์์ต๋๋ค. <input defaultValue="Initial text" />์ ๊ฐ์ ์ด๊น๊ฐ์ ์ ๋ฌํ๋๋ JSX๋ ๋น์ฅ์ ๊ฐ์ ์ ์ดํ์ง ์๊ณ ์ด๊น๊ฐ๋ง์ ์ง์ ํฉ๋๋ค.
์ ์ด๋๋ input์ ๋ ๋๋งํ๋ ค๋ฉด, value (๋๋ ์ฒดํฌ๋ฐ์ค์ ๋ผ๋์ค์๋ checked) prop ์ ์ ๋ฌํ์ธ์. React๋ ์ ๋ฌํ value๋ฅผ ํญ์ ๊ฐ๋๋ก input์ ๊ฐ์ ํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก state ๋ณ์๋ฅผ ์ ์ธํ์ฌ ํ ์ ์์ต๋๋ค.
function Form() {
const [firstName, setFirstName] = useState(''); // state ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
// ...
return (
<input
value={firstName} // ์
๋ ฅ ๊ฐ์ด state ๋ณ์์ ์ผ์นํ๋๋ก ๊ฐ์ ํฉ๋๋ค.
onChange={e => setFirstName(e.target.value)} // input์ ํธ์งํ ๋๋ง๋ค state ๋ณ์๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
/>
);
}์๋ฅผ ๋ค์ด ์์ ํ ๋๋ง๋ค UI๋ฅผ ๋ฆฌ๋ ๋๋ง ํ๋ ๋ฑ state๊ฐ ํ์ํ ๊ฒฝ์ฐ ์ ์ด๋ input์ด ์ ํฉํฉ๋๋ค.
function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
First name:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Your name is {firstName}.</p>}
...๋ํ ๋ฒํผ์ ํด๋ฆญํ๋ ๋ฑ์ input state๋ฅผ ์กฐ์ ํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ค๋ ๊ฒฝ์ฐ์๋ ์ ์ฉํฉ๋๋ค.
function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Age:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Add 10 years
</button>์ ์ด๋๋ ์ปดํฌ๋ํธ์ ์ ๋ฌ๋๋ value๋ undefined ๋ null์ด ๋์ด์๋ ์๋ฉ๋๋ค. ์๋์ firstName ํ๋์ฒ๋ผ ์ด๊น๊ฐ์ ๋น์๋์ด์ผ ํ๋ ๊ฒฝ์ฐ state ๋ณ์๋ฅผ ๋น ๋ฌธ์์ด('')๋ก ์ด๊ธฐํ ํ์ธ์.
import { useState } from 'react'; export default function Form() { const [firstName, setFirstName] = useState(''); const [age, setAge] = useState('20'); const ageAsNumber = Number(age); return ( <> <label> First name: <input value={firstName} onChange={e => setFirstName(e.target.value)} /> </label> <label> Age: <input value={age} onChange={e => setAge(e.target.value)} type="number" /> <button onClick={() => setAge(ageAsNumber + 10)}> Add 10 years </button> </label> {firstName !== '' && <p>Your name is {firstName}.</p> } {ageAsNumber > 0 && <p>Your age is {ageAsNumber}.</p> } </> ); }
ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค ๋ฆฌ๋ ๋๋ง ์ต์ ํํ๊ธฐ
์ ์ด๋ input์ ์ฌ์ฉํ ๋๋ ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค state๋ฅผ ์ค์ ํฉ๋๋ค. state๋ฅผ ํฌํจํ๋ ์ปดํฌ๋ํธ๊ฐ ํฐ ํธ๋ฆฌ๋ฅผ ๋ฆฌ๋ ๋๋งํ ๊ฒฝ์ฐ ์๋๊ฐ ๋๋ ค์ง ์ ์์ต๋๋ค. ๋ฆฌ๋ ๋๋ง ์ฑ๋ฅ์ ์ต์ ํํ ์ ์๋ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค ๋ชจ๋ ํ์ด์ง ๋ด์ฉ์ ๋ฆฌ๋ ๋๋งํ๋ ํผ์ผ๋ก ์์ํ๋ค๊ณ ๊ฐ์ ํด๋ณด์ธ์.
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}<PageContent />๋ input state์ ์์กดํ์ง ์์ผ๋ฏ๋ก input state๋ฅผ ์์ฒด ์ปดํฌ๋ํธ๋ก ์ด๋ํ ์ ์์ต๋๋ค.
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}์ด๋ ๊ฒ ํ๋ฉด ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค SignupForm๋ง ๋ฆฌ๋ ๋๋งํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ด ํฌ๊ฒ ํฅ์๋ฉ๋๋ค.
PageContent๊ฐ ๊ฒ์ input ๊ฐ์ ์์กดํ๋ ๊ฒฝ์ฐ์ฒ๋ผ ๋ฆฌ๋ ๋๋ง์ ํผํ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒฝ์ฐ useDeferredValue๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ ๋ฆฌ๋ ๋๋ง ์ค์๋ ์ ์ด๋ input์ด ์๋ตํ๋๋ก ํ ์ ์์ต๋๋ค.
๋ฌธ์ ํด๊ฒฐ
ํ ์คํธ input์ ํ์ดํ์ ํด๋ ์ ๋ฐ์ดํธ๋์ง ์์ต๋๋ค
onChange ์์ด value๋ง ์ ๋ฌํ์ฌ input์ ๋ ๋๋งํ๋ฉด ์ฝ์์ ์๋ฌ๊ฐ ๋ํ๋ฉ๋๋ค.
// ๐ด ๋ฒ๊ทธ: ์ ์ด๋๋ input์ onChange ํธ๋ค๋ฌ๊ฐ ์์ต๋๋ค.
<input value={something} />onChange ํธ๋ค๋ฌ ์์ด value prop๋ง ์ ๋ฌํ์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๊ธฐ ์ ์ฉ ํ๋๋ฅผ ๋ ๋๋งํ๊ฒ ๋ฉ๋๋ค. ํ๋๊ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅํด์ผ ํ๋ ๊ฒฝ์ฐ defaultValue๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ onChange ๋๋ readOnly๋ฅผ ์ค์ ํ์ธ์.์๋ฌ ๋ฉ์์ง๊ฐ ์ ์ํ๋ฏ ์ด๊น๊ฐ๋ง ์ง์ ํ๋ ค๋ฉด defaultVallue๋ฅผ ๋์ ์ ๋ฌํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋์ง ์๋ input์ ์ด๊น๊ฐ ์ ๋ฌ
<input defaultValue={something} />input์ state ๋ณ์๋ก ์ ์ดํ๋ ค๋ฉด onChange ํธ๋ค๋ฌ๋ฅผ ์ง์ ํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋๋ input์ onChange ์ ๋ฌ
<input value={something} onChange={e => setSomething(e.target.value)} />๊ฐ์ด ์๋์ ์ผ๋ก ์ฝ๊ธฐ ์ ์ฉ์ด๋ผ๋ฉด ์๋ฌ๋ฅผ ๋ง๊ธฐ ์ํด readOnly prop์ ์ถ๊ฐํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋๋ ์ฝ๊ธฐ ์ ์ฉ input์ onChange ์๋ต
<input value={something} readOnly={true} />์ฒดํฌ๋ฐ์ค๋ฅผ ํด๋ฆญํด๋ ์ ๋ฐ์ดํธ๋์ง ์์ต๋๋ค
onChange ์์ด checked๋ง ์ ๋ฌํ์ฌ ์ฒดํฌ๋ฐ์ค๋ฅผ ๋ ๋๋งํ๋ฉด ์ฝ์์ ์๋ฌ๊ฐ ๋ํ๋ฉ๋๋ค.
// ๐ด ๋ฒ๊ทธ: ์ ์ด๋๋ ์ฒดํฌ๋ฐ์ค์ onChange ํธ๋ค๋ฌ๊ฐ ์์ต๋๋ค.
<input type="checkbox" checked={something} />onChange ํธ๋ค๋ฌ ์์ด checked prop์ ์ ๋ฌํ์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๊ธฐ ์ ์ฉ ํ๋๋ฅผ ๋ ๋๋งํ๊ฒ ๋ฉ๋๋ค. ํ๋๊ฐ ๋ณ๊ฒฝ ๊ฐ๋ฅํด์ผ ํ๋ ๊ฒฝ์ฐ defaultChecked๋ฅผ ์ฌ์ฉํ๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ onChange ๋๋ readOnly๋ฅผ ์ค์ ํ์ธ์.์๋ฌ ๋ฉ์์ง๊ฐ ์ ์ํ๋ฏ ์ด๊น๊ฐ๋ง ์ง์ ํ๋ ค๋ฉด defaultChecked๋ฅผ ๋์ ์ ๋ฌํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋์ง ์๋ ์ฒดํฌ๋ฐ์ค์ ์ด๊น๊ฐ ์ ๋ฌ
<input type="checkbox" defaultChecked={something} />์ฒดํฌ๋ฐ์ค๋ฅผ state ๋ณ์๋ก ์ ์ดํ๋ ค๋ฉด onChange ํธ๋ค๋ฌ๋ฅผ ์ง์ ํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋๋ ์ฒดํฌ๋ฐ์ค์ onChange ์ ๋ฌ
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />์ฒดํฌ๋ฐ์ค๊ฐ ์๋์ ์ผ๋ก ์ฝ๊ธฐ ์ ์ฉ์ด๋ผ๋ฉด ์๋ฌ๋ฅผ ๋ง๊ธฐ ์ํด readOnly prop์ ์ถ๊ฐํ์ธ์.
// โ
์ข์ ์: ์ ์ด๋๋ ์ฝ๊ธฐ ์ ์ฉ input์ onChange ์๋ต
<input type="checkbox" checked={something} readOnly={true} />ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค ์ ๋ ฅ ์ปค์๊ฐ input์ ์ฒ์์ผ๋ก ๋์๊ฐ๋๋ค
input์ ์ ์ดํ ๊ฒฝ์ฐ onChange ์์์ state ๋ณ์๋ฅผ DOM์์ ๋ฐ์์จ input ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํด์ผ ํฉ๋๋ค.
state ๋ณ์๋ e.target.value (ํน์ ์ฒดํฌ๋ฐ์ค์์๋ e.target.checked) ์ธ์ ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
function handleChange(e) {
// ๐ด ๋ฒ๊ทธ: input์ e.target.value ์ธ์ ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.
setFirstName(e.target.value.toUpperCase());
}๋น๋๊ธฐ๋ก ์ ๋ฐ์ดํธํ ์๋ ์์ต๋๋ค.
function handleChange(e) {
// ๐ด ๋ฒ๊ทธ: input์ ๋น๋๊ธฐ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}์ฝ๋๋ฅผ ๊ณ ์น๋ ค๋ฉด e.target.value๋ก ๋๊ธฐ ์
๋ฐ์ดํธํ์ธ์.
function handleChange(e) {
// โ
์ ์ด๋๋ input์ e.target.value๋ก ๋๊ธฐ ์
๋ฐ์ดํธํฉ๋๋ค.
setFirstName(e.target.value);
}์ด ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์ง ์์ ๊ฒฝ์ฐ ํค๋ณด๋๋ฅผ ๋๋ฅผ ๋๋ง๋ค input์ด DOM์์ ์ ๊ฑฐ๋ ํ ๋ค์ ์ถ๊ฐ๋๊ณ ์์ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์ค์๋ก ๋ฆฌ๋ ๋๋ง๋ง๋ค state๋ฅผ ์ฌ์ค์ ํ๊ณ ์๋ค๋ฉด ๋ํ๋ ์ ์๋ ํ์์
๋๋ค. ๊ฐ๋ น input์ด๋ input์ ๋ถ๋ชจ ์ค ํ๋๊ฐ ๋งค๋ฒ ๋ค๋ฅธ key ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ๋ฐ๊ฑฐ๋ ์ปดํฌ๋ํธ ํจ์ ์ ์๋ฅผ ์ค์ฒฉ์ํค๋ ๊ฒฝ์ฐ(์ด๋ ์ง์๋์ง ์์ผ๋ฉฐ โ๋ด๋ถโ ์ปดํฌ๋ํธ๊ฐ ํญ์ ๋ค๋ฅธ ํธ๋ฆฌ๋ก ๊ฐ์ฃผ๋๋๋ก ํฉ๋๋ค)์ ํด๋น ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์๋ฌ๊ฐ ๋ฉ๋๋ค. โA component is changing an uncontrolled input to be controlled(์ปดํฌ๋ํธ๊ฐ ์ ์ด๋์ง ์๋ input์ ์ ์ด ์ํ๋ก ๋ณ๊ฒฝํฉ๋๋ค)โ
์ปดํฌ๋ํธ์ value๋ฅผ ์ ๊ณตํ ๊ฒฝ์ฐ ๋ฐ๋์ ์๋ช
์ฃผ๊ธฐ ๋ด๋ด ๋ฌธ์์ด ํ์
์ผ๋ก ๋จ์์ผ ํฉ๋๋ค.
React๋ ์ปดํฌ๋ํธ๋ฅผ ๋น์ ์ดํ ๊ฒ์ธ์ง ์ ์ดํ ๊ฒ์ธ์ง ์๋๋ฅผ ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฒ์์ value={undefined}๋ฅผ ์ ๋ฌํ๋ค๊ฐ ๋์ค์ ๋ค์ value="some string"์ ์ ๋ฌํ ์๋ ์์ต๋๋ค. ์ ์ด๋๋ ์ปดํฌ๋ํธ๋ ํญ์ null์ด๋ undefined๊ฐ ์๋ ๋ฌธ์์ด value๋ฅผ ๋ฐ์์ผ ํฉ๋๋ค.
value๊ฐ API๋ state ๋ณ์์์ ์จ๋ค๋ฉด null์ด๋ undefined๋ก ์ด๊ธฐํ๋ ์ ์์ต๋๋ค. ๊ทธ๋ด ๊ฒฝ์ฐ ๋น ๋ฌธ์์ด('')์ ์ด๊น๊ฐ์ผ๋ก ์ค์ ํ๊ฑฐ๋ value๊ฐ ๋ฌธ์์ด์์ ๋ณด์ฅํ๊ธฐ ์ํด value={someValue ?? ''}๋ฅผ ์ ๋ฌํ์ธ์.
๋ง์ฐฌ๊ฐ์ง๋ก ์ฒดํฌ๋ฐ์ค์ checked๋ฅผ ์ ๋ฌํ๋ ๊ฒฝ์ฐ ๋ถ๋ฆฌ์ธ์์ ๋ณด์ฅํ์ธ์.