React

리액트 여러개의 input상태관리 (State관리)

hihiha2 2023. 2. 28. 01:32

 

리액트에서 여러개의 input상태를 useState를 통해서 관리하는 것을 연습하였다.

input상태를 하나하나 각각 관리하는것은 그래도 이해가 잘됐는데 여러개를 한꺼번에 관리하기 위해서 useState에 객체의 형태로 넣어주고, 그것을 e.target의 name의 값으로 받아오는 작업을 하면서 헷갈리는 지점이 발생하였다.

 

 

그래서 부족했던 부분에 대해서 더 깊게 공부를 하고 이 코드를 완벽히 이해하려고 노력하였다.

내가 부족했던 부분을 크게 정리하면 아래와 같다.

1.. 자바스크립트의 객체의 Key값으로 쓰이는 []값

2. 객체의 구조분해할당

3.이벤트핸들링을 통해서 name의 값을 변경하는 것

 

 

일단 만든 결과물은 아래와 같다. 

두개의 input에 하나는 이름, 하나는 닉네임을 입력하는 창을 만들었다.

개발자도구 - components툴을 통해서 확인을 해보면, 

key 값이 "이름"인 곳의 value값으로 내가 입력한 "hihiha2"가 들어가고

key값이 "nickname"인 곳의 value값으로 또 입력한 값인  "맨땅에헤딩"이 state값으로 들어가있는것을 볼수있다.

 

 

이것을 코드로 나타내보면 아래와 같다.

key값을 굳이 한글인 "이름"으로 적어준 이유는 만들다보니 input의 name속성과 헷갈려서 한눈에 구별가능하도록 하기 위함이다.

(물론 완전 익숙해진 뒤에는 영어로 적어서 코드를 구현하겠다)

import React, { useState } from "react";

const InputSample = () => {
  const [inputs, setInputs] = useState({
    이름: "",
    nickname: "",
  });

  const { 이름, nickname } = inputs;

  const onChange = (e) => {
    const { value, name } = e.target;
    setInputs({
      ...inputs,
      [name]: value,
    });
  };

  const onReset = () => {
    setInputs({
      이름: "",
      nickname: "",
    });
  };
  return (
    <div>
      <input
        name="이름"
        placeholder="이름쓰세요"
        onChange={onChange}
        value={이름}
      />
      <input
        name="nickname"
        placeholder="닉네임쓰세요"
        onChange={onChange}
        value={nickname}
      />
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값:</b>
        {이름}({nickname})
      </div>
    </div>
  );
};

export default InputSample;

 

이제 코드를 하나하나 분석해보겠다.

1️⃣

const [inputs, setInputs] = useState({ 이름: "", nickname: "", });

이 코드는 원래는 각각 따로 useState를 통해 관리하던 값을 구조분해할당을 통해 한줄로 바꿔준것이다. (코드의 가독성을 위해)

 

원래는 아래두줄의 코드처럼 각각 따로 state관리를 해줬을것이다.

const [nameInput, setNameInput] = useState(‘’)
const [nicknameInput, setNicknameInput] = useState(‘’)

2️⃣

const { 이름, nickname } = inputs;

객체를 구조분해할당을 해준 것이다. 

{중괄호}안에 들어간 값들은 key값들이고 오른쪽의 inputs는 객체명이다.

 

const 이름 = inputs.이름
const nickname = inputs.nickname

위의 두줄의 코드를 구조분해할당을 통해 한줄로 줄였다.

이제는 nickname이라고 적으면 inputs.nickname과 같은 효과를 얻을 수 있다.

 

3️⃣ -1

const onChange = (e) => {
const { value, name } = e.target;
setInputs({ ...inputs, [name]: value, }); };

이벤트핸들러 onChange를 통해 target에 이벤트가 발생했을때 어떤 변화가 일어날지를 써준다.

그런 다음, 코드의 가독성을 위해서 또 구조분해할당을 해준다.

위에 진하게 된 부분은 원래는 아래와 같은 코드였을 것이다.

const value = e.target.value
const name = e.target.name

이제는 name이라고만 적어도 이벤트의 타깃인 input의 name을 의미하고

value라고만 적어도 input의 value값을 의미한다.

 

3️⃣ -2

const onChange = (e) => { 
const { value, name } = e.target;
setInputs({ ...inputs, [name]: value, }); };

setter함수인 setInputs를 통해서 Inputs에 변경될 값을 받아준다. 

리액트에서는 객체를 변경할때 꼭 원본을 복사하고 그 뒤에 변경할 값을 덮어쓰는 방식을 써야하므로 ...(스프레드 문법)을 통해서 원본 객체인 inputs를 복사해준 다음에 위에 변수로 선언한 name을 key값으로 넣어준다.

 

위에서 구조분해할당을 해주었기때문에 [name]: value와 같이만 적어줘도 e.target.name : e.target.value와 같은 코드가 된다.

이벤트의 타깃은 input이기 때문에 위의 코드를 실행하면 input의 name속성에는 value값이 value로 들어간다.

 

⭐️ ⭐️ ⭐️ 내가 몰랐던 부분 ⭐️ ⭐️ ⭐️ 

[대괄호]를 통해서 키값을 적어주는 것은 변수를 선언하고 그 실제값을 불러오기 위해서 사용하는 것이다. 
따라서 [e.target.name]이 키값으로 들어간 것은
<input
name="이름">
이므로,key값으로 "이름"이 들어갈 것이다.

🔫 "이벤트의 타깃인 input의 안에 있는 name이 무엇인가? 그 name에 들어간 값을 키값으로 사용하라" 🔫라는 의미이다.
여기서는 name안에 "이름"이라는 값이 들어가 있기 때문에 
inputs안에서 "이름"이라는 key를 찾고 그것의 value값을 새롭게 들어오는 값으로 변경을 해준다.

 

 

이러한 값들이 실질적으로 어떻게 들어가는지 개발자도구의 element툴을 이용해서 눈으로 확인 가능하다.

input안에 "hihiha2"라고 적어준 뒤, 확인을 해보았다.

input의 value속성이 hihiha2로 변경이 된것을 확인할수있다 (최초의 값은 "" 빈칸이다)

 

어떻게 이러한 변화가 일어난 것인지는 코드가 어떻게 값을 받아오고 변경했는지 그 변화가 일어난 순서대로 따라가보면 된다.

 

return 문 안에 있는 코드를 보자.

 <input
        name="이름"
        placeholder="이름쓰세요"
        onChange={onChange}
        value={이름}
      />

이벤트핸들러인 onChange를 통해서 위에 선언해준 onChange함수가 실행된다. 

onChange함수가 실행되면 3️⃣ -1, 3️⃣ -2의 과정을 거치면서 e.target.name: e.target.value가 들어간다(이벤트의 타깃인 input값의 name속성의 키값(이름)안에 새롭게 적힌 값이 value값("hihiha2")으로 들어간다)

 

4️⃣

다시 input의 value를 보자. input의 value에는 inputs의 key값이 "이름"인 것의 value값이 들어갈 것이다.

초기화를 통해 처음에는 ""빈값을 넣어줬기 때문에 처음에는 값이 아무것도 없지만, 첫번째 input창안에 어떤 값을 넣어주면

setter함수인 setInputs를 통해서 값이 전달되고, 이값은 input의 value값으로 들어간다.

value = {이름}       ("") 초기값.  (inputs.이름)
                                              ⬇️
    ("hihiha2") onChange로 인해 setInputs로 새롭게 변경된 값 ([e.target.name]의 value값)                                                                                 "이름" 

 

 

리액트의 input이 여러개인 상황에서 어떻게 state를 효율적으로 관리할 것인지를 공부하였다.

공부하면서 부족하다고 느꼈던 것 위주로 최대한 자세하게 정리를 해봤는데 내가 이해한 내용을 바탕으로 적은 내용이라 맞지 않은 부분이 있을 수 있다. 추후에 또 만들면서 새롭게 안 내용이 있다면 포스팅을 수정해 나가도록 하겠다. 🤓