Container State
state = {
orderForm: {
name: {
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Your name',
},
value: ''
},
street: {
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Your street',
},
value: ''
},
zipCode: {
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Your zipCode',
},
value: ''
},
country: {
elementType: 'input',
elementConfig: {
type: 'text',
placeholder: 'Your country',
},
value: ''
},
email: {
elementType: 'input',
elementConfig: {
type: 'email',
placeholder: 'Your email',
},
value: ''
},
deliveryMethod: {
elementType: 'select',
elementConfig: {
option: [
{value: 'Fastest', displayValue: 'Fastest'},
{value: 'cheapest', displayValue: 'Cheapest'},
]
},
value: ''
},
}
}
위와 같은 state가 있다. orderForm안에 들어갈 input 들은 name, street, zipCode 등이 있다.
Input Component
import React from 'react'
import classes from './Input.css'
const input = (props) => {
let inputElement = null;
switch (props.elementType) {
case ('input'):
inputElement=<input
className={classes.InputElement}
{...props.elementConfig}
onChange={props.changed}
value={props.value} />
break;
case ('textarea'):
inputElement=<textarea
className={classes.InputElement}
{...props.elementConfig}
onChange={props.changed}
value={props.value} />
break;
case ('select'):
inputElement=(
<select
className={classes.InputElement}
onChange={props.changed}
value={props.value}>
{props.elementConfig.option.map(option => (
<option key={option.value} value={option.value}>
{option.displayValue}
</option>
))}
</select>
)
break;
default:
inputElement=<input
className={classes.InputElement}
{...props.elementConfig}
value={props.value} />
}
return (
<div className={classes.Input}>
<label className={classes.Label}>{props.label}</label>
{inputElement}
</div>
)
}
export default input
props의 elementType에 따라 그냥 input이되기도, textarea, select가 되기도 한다.
inputElement 변수에 input값을 담는다.
Container render
render() {
const formElementsArray = []
for (let key in this.state.orderForm) {
formElementsArray.push({
id: key,
config: this.state.orderForm[key]
})
}
let form = (
<form onSubmit={this.orderHandler}>
{formElementsArray.map(formElement => {
return (<Input
key={formElement.id}
elementType={formElement.config.elementType}
elementConfig={formElement.config.elementConfig}
value={formElement.config.value}
changed={(event) =>this.inputChangedHandler(event, formElement.id)}
/>)
})}
<Button btnType="Success" clicked={this.orderHandler}>Order</Button>
</form>
)
if (this.state.loading) {
form = <Spinner />
}
return (
<div className={classes.ContactData}>
<h4>Enter your Contact Data</h4>
{form}
</div>
);
}
1. formElementsArray 변수에 {id, config}의 형태로 push
2. map으로 for문을 돌면서 Input 값을 생성(return) 해준다.
2-1. changed 매개변수로 사용자의 키보드 입력값을 받을 함수를 넘겨준다.
inputChangedHandler 함수
inputChangedHandler = (event, inputIdentifier) => {
const updatedOrderForm = {
...this.state.orderForm
}
const updatedFormElement = {
...updatedOrderForm[inputIdentifier]
}
updatedFormElement.value = event.target.value
updatedOrderForm[inputIdentifier] = updatedFormElement
this.setState({orderForm: updatedOrderForm})
}
Input Component의 onChange event가 발생하면 매개변수로 이벤트 발생 input값과 그 input 값을 찾기 위한 inputIdentifier을 받는다.
immutable하게 state를 업데이트 해준다.
Form Submit
orderHandler = (event) => {
event.preventDefault()
this.setState({loading: true})
const formData = {}
for (let formElementIdentifier in this.state.orderForm) {
formData[formElementIdentifier] = this.state.orderForm[formElementIdentifier].value
}
const order = {
ingredients: this.props.ingredients,
price: this.props.price,
orderData: formData
}
axios.post('/orders.json', order)
.then(res=> {
this.setState({loading: false})
this.props.history.push('/')
})
.catch(error => {
this.setState({loading: false})
})
}
1. render 함수의 form Tag에서 onSubmit으로 orderHandler 함수 정의
2. state의 orderForm을 immutable하게 formData 변수로 생성
3. axios post Call 실행
'React' 카테고리의 다른 글
React useCallback 이해하기 (0) | 2022.01.13 |
---|---|
React(SPA) Auth 로그인 흐름 (0) | 2020.01.09 |
React Redux 기본 (0) | 2019.12.19 |