사용자로부터 값을 입력받는 form 태그는 자주 사용한다.
textarea, input select 등 여러 태그가 있다.
리액트에서는 이러한 form 태그를 쉽게 다룰 수 있도록 만들어 놓았다.
특히 value 를 번거롭게 다루지 않고 손쉽게 다룰 수 있도록 해 두었다.
<body>
<div id="root1">
</div>
<div id="border1"></div>
<div id="root2">
</div>
<div id="border2"></div>
<textarea id="ta">
</textarea>
<div id="root3">
</div>
<div id="border3"></div>
<div id="root4">
</div>
<div id="border4"></div>
<div id="root5">
</div>
<div id="border5"></div>
<!-- react cdn -->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<!-- react dom cdn -->
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<!-- babel cdn -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- define type as a babel -->
<script type="text/babel">
class MakeBorder extends React.Component {
render() {
return <p>--------------------------------root{this.props.num}----------------------------</p>;
}
}
// 리액트가 form 요소를 비롯하여 다양한 사용자 입력 태그들을 어떻게 다루는지 알아보자.
// 제어 컴포넌트 (Controlled Component)
// 제어 컴포넌트는 리액트가 관리하고 제어하는 컴포넌트를 말한다.
// 리액트가 컴포넌트의 무엇을 관리하고 무엇을 제어한다는 말인가?
// 사용자가 입력하는 입력값들을 리액트가 관리하며, 컴푸넌트에 발생하는 입력과 츨력을 관리한다.
// 컴포넌트 안에서 모든 값들이 결국 리액트의 staate 로 모이고, state로부터 나온다.
// 예를 들어 아래 컴포넌트를 보자
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {val: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
console.log('------------------------------');
console.log('change > val');
console.log(e.target.value);
console.log('state > val');
console.log(this.state.val);
if(this.props.isControl) {
this.setState({val: e.target.value});
}
}
handleSubmit(e) {
e.preventDefault();
console.log('------------------------------');
console.log('submit > val');
console.log(e.target.querySelector('input[type="text"]').value);
console.log('state > val');
console.log(this.state.val);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" value={this.state.val} onChange={this.handleChange} />
<input type="submit" value="click to submit" />
</form>
);
}
}
ReactDOM.render( <NameForm isControl={true}/>, document.getElementById('root1') );
ReactDOM.render( <MakeBorder num="1" />, document.getElementById('border1') );
// 총 세 곳에서 state를 주거나 받는다.
// 첫째는 사용자가 폼을 조작할 수 있는 input 태그다.
// 둘째는 사용자가 input 태그를 조작했을 때 발생하는 이벤트 핸들러다.
// input 태그 ===> 이벤트 핸들러 ===> 리액트 state
// 리액트 state ===> input 태그
// input:text 태그에서 value={this.state.val} 가 없다면 어떻게 될까.
// value 값을 리액트 state로부터 받아오는 값이 아니므로 컴포넌트가 들고 있는 값이랑 시용자가 화면에서 보는 값이랑 다를 수 있다.
// 이벤트 핸들러에서 this.setState({val: e.target.value}); 가 없다면 어떻게 될까.
// 사용자가 입력한 값이 리액트 state의 값을 바꾸지 못하므로 해당 값을 불러다 쓰는 곳들에서 변화가 없는 것처럼 보인다.
// input:text에 value={this.state.val} 를 설정해 두었다면 화면상 값이 변하지 않고, 설정하지 않았다면 화면상으로는 변해도 내부적으로 state값은 변하지 않았음을 input:submit으로 알 수 있다.
ReactDOM.render( <NameForm isControl={false}/>, document.getElementById('root2') );
ReactDOM.render( <MakeBorder num="2" />, document.getElementById('border2') );
// textarea 태그
// html 에서는 textarea가 text를 자식 노드로 가지고 있다.
document.getElementById('ta').childNodes[0].data="check the child node type of this text";
// 리액트에서는 textarea에 value라는 속성을 대신 넣어준다.
class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state={val:''}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
console.log('input');
console.log(e.target.value);
this.setState({val: e.target.value})
console.log('state');
console.log(this.state.val);
}
handleSubmit(e) {
e.preventDefault();
console.log('state');
console.log(this.state.val);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<textarea cols="30" rows="10" value={this.state.val} onChange={this.handleChange}></textarea>
<input type="submit" value="click to submit" />
</form>
);
}
}
ReactDOM.render( <EssayForm />, document.getElementById('root3') );
ReactDOM.render( <MakeBorder num="3" />, document.getElementById('border3') );
// select 태그
// html에서 select 태그는 드롭다운 목록을 만든다.
// 예를 들어 아래 select 태그는 사용자가 과일 목록을 선택할 수 있도록 만든다.
// <select>
// <option value="grapefruit">Grapefruit</option>
// <option value="lime">Lime</option>
// <option selected value="coconut">Coconut</option>
// <option value="mango">Mango</option>
// </select>
// 초기값은 selected 속성이 들어 있는 coconut 항목이다.
// 사용자가 값을 선택하면 그 option 태그에 selected 속성이 추가된다.
// html 에서는 선택한 값에 접근하려면 select 하위 속성인 option 요소들 중에서 selected 속성이 있는 요소를 골라내야 한다.
// 리액트에서는 option 태그에 있는 selected 속성을 사용하지 않는다.
// 대신 리액트에서는 select 태그 자체에 value 라는 속성을 사용한다.
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {val: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
console.log('input > val');
console.log(e.target.value);
this.setState({val: e.target.value})
console.log('state > val');
console.log(this.state.val);
}
handleSubmit(e) {
e.preventDefault();
console.log('state > val');
console.log(this.state.val);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<select value={this.state.val} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
<input type="submit" value="click here to submit" />
</form>
);
}
}
ReactDOM.render( <FlavorForm />, document.getElementById('root4') );
ReactDOM.render( <MakeBorder num="4" />, document.getElementById('border4') );
// 다중 입력 제어하기.
// 리액트 컴포넌트에서 여러 input 엘리먼트를 제어해야 하는 경우가 있다.
// 각 엘리먼트에 name 속성을 추가해 두고 그 값에 따라 핸들러가 다른 처리를 하도록 만들 수도 있다.
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {isFamily: false, numberOfGuests: 0};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
let val;
if(e.target.name == 'family') {
console.log('family > val');
val = {isFamily: e.target.checked};
} else if(e.target.name == 'num') {
console.log('num > val');
val = {numberOfGuests: e.target.value};
} else {
console.log('unknown > val');
val = {isFamily: false, numberOfGuests:0};
}
this.setState(val);
console.log('state > val');
console.log(this.state);
}
handleSubmit(e) {
e.preventDefault();
console.log('state > val');
console.log(this.state);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Is Family Guest:
<input type="checkbox" name="family" checked={this.state.isFamily} onChange={this.handleChange} />
</label>
<br />
<label>
Number of Guests:
<input type="number" name="num" value={this.state.numberOfGuests} onChange={this.handleChange} />
</label>
<input type="submit" value="click to submit" />
</form>
);
}
}
ReactDOM.render( <Reservation />, document.getElementById('root5') );
ReactDOM.render( <MakeBorder num="5" />, document.getElementById('border5') );
// 덧붙임 - ES6 문법: 객체 key 값에 변수값 넣기
let result = {hello: 'world'};
// 위와 같은 객체를 만들려고 할 때, key 값에 들어가야 하는 값을 다른 변수가 들고 있다면 쉽게 하는 방법이 있다.
let keyVal = 'hello';
result = {};
result[keyVal] = 'world';
// 위는 ES5 문법이다.
// 더 간단하게 만들 수 있도록 ES6부터는 아래와 같은 문법도 가능해졌다.
result = {[keyVal]: 'world'};
</script>
</body>
- 220601
참고자료 -
반응형
'React' 카테고리의 다른 글
[React] 주요 LifeCycle 함수들 호출 시점 / 활용 방법 / 주의할 점 정리 (0) | 2022.12.05 |
---|---|
[React] componentDidUpdate 사용 시점과 무한 루프 렌더링 주의 (0) | 2022.11.28 |
React 시작하기 - 08 - 리스트 반복문으로 엘리먼트 만들기, key 개념 (0) | 2022.06.18 |
React 시작하기 - 07 - 조건부 렌더링, 조건에 따라 다른 요소 렌더링 (0) | 2022.06.18 |
React 시작하기 - 06 - 이벤트 핸들링하기, this 바인딩 해주기, e 합성 이벤트 (0) | 2022.06.18 |