[React] Complex한 state 관리

2023. 8. 31. 13:50기술 창고/React

728x90
SMALL

이번에는 기존의 state 관리하는 방법보다 좀 더 복잡한 state를 관리하는 방법에 대해서 정리해보겠습니다.
Complex State란 자바스크립트 개체 상태를 좀 더 복잡한 관리를 말합니다.
개체의 이전 값을 돌려받거나 사용해야할 경우의 관리를 말합니다.
예를 들어 웹사이트에 두 가지의 값을 입력하면 두 가지 입력 정보를 이용해 사용자에게 보여지게끔 할 수 있게 만드는 것입니다. 

예시로 든 두 가지의 값 입력 사이트로 확인해보겠습니다.

 

 

기존의 useState 관리 방식

App.jsx

import React, { useState } from "react";

function App() {
  const [firstName, setFirstName] = useState(""); 
  const [secondName, setSecondName] = useState(""); 
  const [fullName, setFullName] = useState("");

  function firstNameWrite(name){
    setFirstName(name.target.value);
  }

  function secondNameWrite(name){
    setSecondName(name.target.value);
  }

  function fullNameWrite(){
    setFullName(firstName + " " + secondName);
  }

  return (
    <div className="container">
      <h1>Hello {fullName}</h1>
      <form>
        <input onChange={firstNameWrite} type="text" name="fName" placeholder="First Name" />
        <input onChange={secondNameWrite} type="text" name="lName" placeholder="Last Name" />
        <button onClick={fullNameWrite}>Submit</button>
      </form>
    </div>
  );
}

export default App;

예시 코드에서 보이다시피 기존의 다수의 useState를 활용해 간단하게 state를 제어하고 관리하여 버튼을 눌렀을 때 사이트에 보여지는 것을 확인할 수 있습니다.
이런 식으로 개별적으로 useState 변수를 생성해서 사용할 수도 있지만 이럴 경우 보다 복잡하거나 많은 수의 값들의 state를 관리하게 될 떄 코드의 양도 늘어날 뿐만 아니라 비효율적이라고 볼 수 있습니다.
때문에 다수의 값들에 대한 state를 관리하고자 할 때 useState 변수를 개체로 state를 관리하게끔 하면 편리합니다.

 

 

개체 Complex State 관리 방식

App.jsx

import React, { useState } from "react";

function App() {
  const [fullName, setFullName] = useState({
    fName: "",
    lName: ""
  });
  
  function fullNameWrite(name) {
    const nameValue = name.target.value;
    const inputName = name.target.name;

    if (inputName === "fName") {
      setFullName({ fName: nameValue });
    } else {
      setFullName({ lName: nameValue });
    }
  }


  return (
    <div className="container">
      <h1>
        Hello {fullName.fName} {fullName.lName}
      </h1>
      <form>
        <input
          onChange={fullNameWrite}
          type="text"
          name="fName"
          placeholder="First Name"
          value={fullName.fName}
        />
        <input
          onChange={fullNameWrite}
          type="text"
          name="lName"
          placeholder="Last Name"
          value={fullName.lName}
        />
        <button>Submit</button>
      </form>
    </div>
  );
}

export default App;

두 개의 개별적인 useState 변수들을 fullName useState 하나로 fName, lName 값을 가지고 있는 개체로서 관리하게끔 만들어주었습니다.
두 input 태그에 입력했을 경우에 동작하는 함수를 fullNameWrite 함수 하나로 공통되게 사용되며 각각 입력했을 경우 input 태그의 name 속성에 따라 if 문을 통해 그에 따른 fullName의 fName, lName의 값에 반영되게끔 하는 것입니다.

 

하지만 이럴 경우 정상적으로 동작이 수행되는 것처럼 보이지만 두 개의 입력값을 부여했을 때 하나의 input 태그 값만이 보여지게 됩니다.
왜일까요?

 

선 입력한 d 키워드가 보이지 않는다.


원인을 한번 보겠습니다.

 

fname 선입력 후 lname 후입력
lname 선입력 후 fname 후입력

개발자 도구에서 React components 항목의 hooks 내용을 봅니다.
처음에 가장 마지막에 작성한 ccff 라는 단어가 state로서 유지되고 xdd 라는 단어는 state에서 지워진 것을 볼 수 있습니다.
반대로 다시 xddggg 단어를 입력했을 때 ccff  state가 지워진 것을 볼 수 있습니다.

따라서 단순히 개체로 관리되는 useState 변수에 if 문을 사용해서 개체 내에 있는 특정 속성값을 반영시키고자 할 때, 기존의 값을 유지시키는 로직을 추가하지 않으면 반영된 특정 속성값만 반영이 되고 나머지 속성은 null 값으로 처리되는 것입니다.
위의 예시 코드에서는 name 속성이 fName 일 경우 setFullName을 통해 fullName.fName만을 바꿔주도록 되어있기 때문에 lName은 null 지정되게 됩니다.
그래서 가장 마지막에 입력한 input 값만 적용되고 최초로 입력된 input 값은 초기화 되어 보이지 않는 것입니다.

이를 보완하기 위해서는 이전에 입력된 값을 보관하고 관리한 상태를 유지해야 합니다.
이것이 바로 Complex State(복잡한 State 관리) 라고 할 수 있는 것입니다.
Complex state를 수행할 대표적인 방법 중 하나는 arrow function과 input 태그의 value 속성을 사용하는 것입니다.

 

 

보완한 Complex State 관리 방식

App.jsx

import React, { useState } from "react";

function App() {
  const [fullName, setFullName] = useState({
    fName: "",
    lName: ""
  });

  function fullNameWrite(event) {
    const {value, name} = event.target;

    setFullName((preValue) => {
      if (name === "fName") {
        return {
          fName: value,
          lName: preValue.lName
        };
      } else {
        return {
          fName: preValue.fName,
          lName: value
        };
      }
    });
  }

  return (
    <div className="container">
      <h1>
        Hello {fullName.fName} {fullName.lName}
      </h1>
      <form>
        <input
          onChange={fullNameWrite}
          type="text"
          name="fName"
          placeholder="First Name"
          value={fullName.fName}
        />
        <input
          onChange={fullNameWrite}
          type="text"
          name="lName"
          placeholder="Last Name"
          value={fullName.lName}
        />
        <button>Submit</button>
      </form>
    </div>
  );
}

export default App;

input 태그에 입력될 시 수행될 fullNameWrite 함수 로직에 arrow function을 추가합니다.
useState의 setFullName 변수에 arrow function을 넣어줍니다.
만약 name 속성이 fName 일 경우 fName 속성 값을 현재 input 태그의 value 속성 값을 넣어줍니다.
반대로 name 속성이 lName 일 경우 lName 속성 값을 현재 input 태그의 value 속성 값을 넣어줍니다.

input 태그의 value 속성은 사용자가 직접 입력한 값을 의미합니다.
처음에 fName을 입력 후 lName을 입력하게되면 arrow function의 preValue 매개변수에 기존에 처음 입력헀던 fName의 value 값이 저장됩니다.
따라서 새로 입력할 때마다 기존에 입력되었던 값은 preValue에 저장된 상태를 유지하고 새로 입력한 속성 값만이 업데이트 됩니다.

 

개발자 도구에서 확인했을 때도 state 개체에 저장된 값이 모두 존재하는 것을 확인할 수 있습니다.
이렇게 해서 기존의 state 관리 방식보다 조금 더 복잡한 Complex State 관리에 대해서 알아보았습니다.

728x90
반응형
LIST