input 여러 개 일때 useState를 여러개 사용하는건 좋은 방법이 아님.
좋은 방법은, input에 name이라는 값을 설정하고, 이벤트가 발생했을 때 이값을 참조하는거다.
여러개의 문자열 형태를 가지고 있는 객체 형태를 관리 해 줘야한다.
function InputSample(){
const [inputs, setInputs] = useState({
name:'',
nickname:'',
});
const {name, nickname} = inputs;
const onChange = (e)=>{
console.log(e.target.name);
console.log(e.target.value);
}
const onReset = ()=>{
}
return (
<div>
<input name="name" placeholder="이름" onChange={onChange}/>
<input name="nickname" placeholder="닉네임" onChange={onChange}/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
이름 (닉네임)
</div>
</div>
);
}
export default InputSample;
이 값들을 참조해서 객체를 업데이트 해 주면 되는건데,
기존의 객체를 복사 해야한다.
...inputs 이건 spread문법인데 이 문법은 객체 혹은 배열을 펼칠 수 있다.
https://learnjs.vlpt.us/useful/07-spread-and-rest.html?q=
function InputSample(){
const [inputs, setInputs] = useState({
name:'',
nickname:'',
});
const {name, nickname} = inputs;
const onChange = (e)=>{
const {name, value} = e.target;
const nextInputs = {
//spread 문법. 현재 상태의 내용이 이 자리로 온다.
...inputs,
[name] : value,
};
//객체를 새로운 상태로 쓰겠다.
setInputs(nextInputs);
};
const onReset = ()=>{
};
return (
<div>
<input name="name" placeholder="이름" onChange={onChange}/>
<input name="nickname" placeholder="닉네임" onChange={onChange}/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
이름 (닉네임)
</div>
</div>
);
}
export default InputSample;
nextInputs 에 ...inputs을 사용해서 input한거 그대로 사용 하면서 name만 value로 덮어준다.
const nextInputs = {
//spread 문법. 현재 상태의 내용이 이 자리로 온다.
...inputs,
name:value,
};
이렇게 하면 문자열 name자체가 들어가지게 되는데
[name]:value,
해주면 name값에 따라 다른 key값이 변경됨.
input이 세개 이상이어도 문제없다.
import React, { useState } from 'react'
const InputComponent = () => {
const [input, setInput] = useState({
input1: '',
input2: '',
input3: ''
})
const { input1, input2, input3 } = input; // destructuring
const onChangeInput = (e) => {
const {name, value} = e.target // destructuring
setInput({
...input,
[name]:value
})
}
return (
<div>
<input type="text" name="input1" value={input1} onChange={onChangeInput}/>
<input type="text" name="input2" value={input2} onChange={onChangeInput}/>
<input type="text" name="input3" value={input3} onChange={onChangeInput}/>
</div>
)
}
export default LoginPage
만약 React JSX문법에서 .map
내부에 Dynamically change input's name을 하고 싶다면 어떻게 할까?
예시를 보면
{this.props.items.map((item, idx) => (
<input type="text" name="name{idx}" ... />
))}
map함수를 사용해서 name값에 고정된 string과 idx를 합쳐서 부여하고 싶다고 가정하자.
name="name0"
name="name1"
name="name2"
...
이런 식으로 표현하려면 ${}
에 변수를 사용해주거나
<input type="text" name = {`name${idx}`} ... />
"string" + 변수
로 표현해 주면 된다.
<input type="text" name = {"name" + idx} ... />
import React, { useState } from 'react'
const InputComponent = () => {
const [input, setInput] = useState({
input0: "",
input1: "",
input2: "",
input3: "",
input4: "",
});
const handleTextValueChange = (e) => {
const { name, value } = e.target;
setInput((input) => {
return { ...input, [name]: value };
});
};
return (
{uniqueArr.map((index) => (
<input
type="text"
id={`input${index}`}
name={`input${index}`}
placeholder="변수입력"
onChange={handleTextValueChange}
value={`input${index}`.value}
/>
))}
)
}
export default LoginPage
객체 상태를 업데이트 할 때는 꼭 기존의 상태를 한번 복사하고 나서 특정값을 덮어 씌우고 새로운 값을 설정 해주어야함. : 이걸 불변성을 지켜준다고 함.
이렇게 해야 업데이트 된 것을 감지하고 랜더링이 됨.
객체 상태를 업데이트 할 때는 spread문법으로 객체를 복사하고, 특정값을 덮어씌워서 상태를 업데이트 해 주어야한다.
이건 배열 상태를 관리 할 때에도 마찬가지이고 불변성을 지켜줘야지만 최적화도 되는 것이다.