[React] input이 여러개 일때 상태 관리하기 / 계산된 속성명 사용

sujin·2022년 9월 13일
0

React

목록 보기
9/17
post-thumbnail

useState가 어느 정도 익숙해진 것 같으니(?) 좀더 심화적인 내용을 다뤄볼까 한다. 바로 이름부터 낯선 계산된 속성명이라는 개념인데 이것이 무엇이고 어떻게 쓰이는지 살펴보도록 하자!


계산된 속성명이란?

계산된 속성명이란 ES6부터 지원되는 기능으로 객체의 속성명이 최초에 결정되는 것이 아니라 동적으로 결정되는 것을 말한다. 이때 객체에 접근을 할때는 dot notation이 아니라 []을 사용한다.

// 계산된 속성명 미사용
const before = (name, value) => {
	const obj = {};
  	obj[name] = value;
  	return obj;
}

// 계산된 속성명 사용
const after = (name, value) => {
	return {[name]: value}  //계산된 속성명 [name]
    //[name]값이 name의 이름으로 동적으로 할당됨
}
  • 위 코드에서 name이라는 매개변수를 통해서 return안에 [name]이 동적으로 계산되면서 상황에 맞게 들어가는 것을 알 수 있다.
  • 만약 여기서 []를 사용하지 않으면, name에 들어오는 인자가 아닌 name이라는 이름을 가진 프로퍼티에 value가 할당되기 때문에 원하는 대로 동작하지 않을 것이다!

계산된 속성명을 사용하는 이유는?

  • 계산된 속성명을 사용하면 비슷한 동작을 줄일 수 있다.
  • 예를 들어 똑같이 input의 값을 받아 저장만 하는 state를 여러개 만드는 것은 불필요하다.


여러개의 input 상태관리

input값은 useState를 통해서 상태 관리가 이루어졌다. 여기서 만약 input이 여러개라면 각각에 해당하는 state를 생성해줘야 할 것이다.

//수정 전

import { useState } from "react";

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassWord] = useState("");

  const saveUserEmail = e => {
    setEmail(e.target.value);
  };
  const saveUserPassword = e => {
    setPassWord(e.target.value);
  };

  return (
    <div className="login">
      <div className="container">
        <h1 className="logo">Instagram</h1>
        <form>
          <input
            type="text"
            name="email"
            placeholder="이메일"
            onChange={saveUserEmail}
          />
          <input
            type="password"
            name="password"
            placeholder="비밀번호"
            autoComplete="on"
            onChange={saveUserPassword}
          />
          <button className="login-btn">로그인</button>
        </form>
      </div>
      <div className="container sm">
        <p>
          계정이 없으신가요?
          <button className="signup-btn">가입하기</button>
        </p>
      </div>
    </div>
  );
};

export default Login;

위의 코드 처럼 늘어난 input갯수 만큼 input을 관리하기 위한 stateonChange 함수를 생성할 것이다.

하지만 이는 좋은 방법이 아니다. input에 name을 설정하고 이벤트가 발생했을 때 이 값을 참조하는 것이 코드의 가독성도 좋아지고 나중에 유지보수 관리도 수월 할 것이다.

하나의 state로 input값들을 설정 할 수 있도록 위의 코드를 수정해보자!

// 수정 후 
import { useState } from "react";

const Login = () => {
  const [inputValue, setInputValue] = useState({
    // 사용할 문자열들을 저장하는 객체 형채로 관리
    email: "",
    password: "",
  });

  const handleInput = (e) => {
    const { name, value } = e.target;
    setInputValue({ ...inputValue, [name]: value }); 
    // name 키에 맞는 키값(value)를 가져온다. => 계산된 속성명 
  };

  return (
    <div className="login">
      <div className="container">
        <h1 className="logo">Instagram</h1>
        <form>
          <input
            type="text"
            name="email"
            placeholder="이메일"
            onChange={handleInput}
          />
          <input
            type="password"
            name="password"
            placeholder="비밀번호"
            autoComplete="on"
            onChange={handleInput}
          />
          <button className="login-btn">로그인</button>
        </form>
      </div>
      <div className="container sm">
        <p>
          계정이 없으신가요?
          <button className="signup-btn">가입하기</button>
        </p>
      </div>
    </div>
  );
};

export default Login;

  • input에 name이라는 값을 설정하고 이벤트가 발생했을 때 그 값을 참조한다.
  • 이전에 useState 함수가 문자열을 관리해줬다면, 여기에서는 여러개의 문자열을 갖고 있는 객체 형태로 관리 해줘야한다.
  • 그리고 <input />에 name을 속성을 부여 해줘야 하는데, onChange함수에서 e.target.name를 조회하면 변화된 값이 어떤 name인지 알 수 있다.
  • input의 상태 관리를 위한 하나의 state를 만들어 주고 값이 바뀔 때 마다 객체 spread방식 ...inputValue 으로 값을 업데이트 해준다.

💡 spread방식을 사용하는 이유

  • 객체 상태를 업데이트 할 때는 꼭 기존의 상태를 한번 복사하고 나서 특정값을 덮어 씌우고 새로운 값을 설정 해주어야한다. 이것을 불변성을 지켜준다고 함. 이렇게 해야 리액트에서 업데이트 된 것을 감지하고 랜더링한다.
  • 불변성 을 지켜줘야지만 나중에 컴포넌트 업데이트 성능을 최적화시켜줄 수 있다.
  • spread 방식 사용 전
  • spread 방식 사용 후

    ➡️ 사용전에는 전에 입력된 이메일 값이 초기화되어 없어지지만 사용후에는 입력값이 누적되어 새로운 값이 추가로 입력되는 것을 볼 수 있다.

마무리✨

여러 줄의 코드를 한줄로 줄이는 것에 쾌감을 느끼고 개발자는 게을러야 한다는 말을 오늘도 마음에 새기며 저는 마저 코딩하러 갑니다🥲

profile
개발댕발

0개의 댓글