Front-End

vsoghlv@naver.com

React.js input 상태관리

하나의 인풋관리

하나의 input 관리는 크게 어렵지 않다. input 의 상태관리를 할 때도 버튼과 마찬가지로 useState 를 사용해 작업한다. 먼저 useState 로 text 값을 관리할 수 있게 만든 후 기본값으로 공백을 주고 input onChange 이벤트가 있을때 마다 onChange() 함수를 줘 setText() 를 통해 input 의 value 를 text로 넣어주면 된다.

import React, { useState } from "react";

function InputSample() {
  const [text, setText] = useState("");
  const onChange = (e) => {
    setText(e.target.value);
  };
  const onReset = () => {
    setText("");
  };
  return (
    <div>
      <input onChange={onChange} value={text} />
      <button onClick={onReset}>초기화</button>
      <div>
        <b> : </b>
        {text}
      </div>
    </div>
  );
}

export default InputSample;

만약 input 의 value 에 {text} 를 주지 않는다면 초기화 버튼 등, 다른 곳에서 text 의 값을 수정했을 때 input 은 변화가 없으니 주의해야한다.

결과

값 : sunsunsun

input 이 여러 개일 때

input 이 여럿인 경우 먼저 input 에 name 값을 줘 그것을 참조하게 하고 useState 에서는 객체를 사용해 관리하는 방법을 사용하는게 좋다. 물론 useState 를 여러개 작성해서 사용해도 되기는 하지만 그건 효율성 측면이든 가독성 측면에서든 좋지 않은 방법이다. 먼저 input 을 아래와 같이 만드는데 input 을 컨트롤 하기 위해 name 값을 설정해준다.

<div>
  <input name="name" placeholder="이름" onChange={onChange} />
  <input name="nickName" placeholder="닉네임" onChange={onChange} />
  <button onClick={onReset}>초기화</button>
  <div>
    <b>값 : </b>
  </div>
</div>

useState 에는 객체를 넣고, name 과 nickName 을 비구조화 할당을 이용해 추출해준다.

  const [inputs, setInputs] = useState({
    name: "",
    nickName: "",
  });
  const { name, nickName } = inputs;

그 후 onChange 를 수정해보자.

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

    setInputs(nextInputs);
  };

객체 상태를 업데이트 해줄 때는 반드시 기존의 상태를 복사한 후 거기에 새로운 값을 덮어씌우고 새로운 상태로 설정해줘야 한다. 이것을 불변성을 지킨다고 하는데 불변성을 지켜줘야만 리액트 컴포넌트에서 상태가 변경된 것을 감지할 수 있고 이에 따라 필요한 렌더링이 발생하게 된다.

따라서 스프레드 문법을 이용해 inputs 를 복사해 새로운 객체를 만들고 [name] 에 value 를 넣어 setInputs 에 새로 만든 객체를 넣어준다. 이때 name : value 이런 식으로 대괄호 없이 사용할 경우 name 이라는 문자열이 들어가니 주의해야 한다. 대괄호로 감싸주면 name 이 무엇을 가리키냐에 따라 키값이 변경된다. 위의 문장을 조금 더 간단하게 만들면 굳이 nextInputs 를 만들지 않고 setInput 안에서 바로 로직을 실행해주면 된다.

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

이제 onReset 도 같은 방법으로 inputs 의 name 과 nickName 을 빈값으로 바꾸어주고 input 에 각각의 value 값을 넣어주면 된다.

import React, { useState } from "react";

function InputSample() {
  const [inputs, setInputs] = useState({
    name: "",
    nickName: "",
  });
  const { name, nickName } = inputs;
  const onChange = (e) => {
    const { name, value } = e.target;
    setInputs({ ...inputs, [name]: value });
  };
  const onReset = () => {
    setInputs({
      name: "",
      nickName: "",
    });
  };
  return (
    <div>
      <input 
        name="name" 
        placeholder="이름" 
        onChange={onChange} 
        value={name} />
      <input
        name="nickName"
        placeholder="닉네임"
        onChange={onChange}
        value={nickName}
      />
      <button onClick={onReset}>초기화</button>
      <div>
        <b> : </b>
        {name}({nickName})
      </div>
    </div>
  );
}

export default InputSample;
값 : 선(Sun)