본문 바로가기
리액트

[React] 리액트에서 Input이 여러 개일 때 효율적으로 State 관리하기

by 지 요니 2023. 4. 21.

아래는 input으로 제목과 내용을 입력받아 Todolist에 저장하는 코드이다.

 

Input.js

 import React from "react";
 
 const Input = () =>{
 return (
    <section>
      <form className="add-form" onSubmit={onSubmitHandler}>
        <div className="input-group">
          <label className="form-label">제목</label>
          <input
            required
            className="add-input"
            type="text"
            name="title"
            value={todo.title}
            onChange={titleChange}
          />
          <label className="form-label">내용</label>
          <input
            required
            className="add-input"
            type="text"
            name="contents"
            value={todo.contents}
            onChange={contentsHandler}
          />
        </div>
        <button className="add_btn">추가하기</button>
      </form>
    </section>
    );
    };
    
    export default Input;

 

 

Input 2개와 버튼 1개가 있을 때, 각 Input마다 state를 생성하고 각 state를 업데이트를 작성하였다.

function Input({ setTodos, todos }) {

//input state
  const [title, setTitle] = useState("");
  const [contents, setContents] = useState("");

//각 state 업데이트할 함수
  const titleChange = (event) => {
    setTitle(event.target.value);
  };
  const contentsChange = (event) => {
    setContents(event.target.value); 
  };
  
  const onSubmitHandler = (event) => {
    event.preventDefault();
    const newTodo = {
      title,
      contents,
      isDone: false,
      id: uuidv4(),
    };

    setTodos([...todos, newTodo]); //불변성 유지
    setTtile("");
    setContents("");
  };

 

 

각 input에 따른 useState를 작성하고 각 State를 업데이트 해 줄 함수도 작성하면 코드가 길어져 비효율적이다.

 

 

Input의 정보를 객체형태로 useState 하나에 작성하고 하나의 함수를 이용하여 코드를 간결하게 작성해보자!

 

title과 contents을 todo라는 객체로 useState 하나에 작성한 코드는 다음과 같다.

 

import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";

function Input({ setTodos, todos }) {
  const initState = {
    id: 0,
    title: "",
    contents: "",
    isDone: false,
  };
  const [todo, setTodo] = useState(initState);
  const onChangeHandler = (event) => {
    //value = title, neme = contents
    const { value, name } = event.target;
    //얕은복사로기존값복사하고 새로추가된 값들 대입
    setTodo({ ...todo, [name]: value, id: uuidv4() });
  };
  const onSubmitHandler = (event) => {
    event.preventDefault();
    setTodos([...todos, todo]); //불변성 유지
    //input창 비우기
    setTodo(initState);
  };

  return (
    <section>
      <form className="add-form" onSubmit={onSubmitHandler}>
        <div className="input-group">
          <label className="form-label">제목</label>
          <input
            required
            className="add-input"
            type="text"
            name="title"
            value={todo.title}
            onChange={onChangeHandler}
          />
          <label className="form-label">내용</label>
          <input
            required
            className="add-input"
            type="text"
            name="contents"
            value={todo.contents}
            onChange={onChangeHandler}
          />
        </div>
        <button className="add_btn">추가하기</button>
      </form>
    </section>
  );
}

export default Input;

 

아래 그림은 onChangeHandler안에있는 event.target을 console에 찍은 값이다.

event.target

value에 우리가 입력한 값이 저장되고, name으로 title과 contents가 구분됨을 알 수 있다 

따라서,  const { value, name } = event.targe; 은 비구조화 할당으로 값을 추출한 것이다.

 

setTodo({ ...todo, [name]: value, id: uuidv4() });

- ...todo : 불변성을 유지하기위해, spread문법으로 todo 객체를 펼쳐 객체를 복해주었다.
-  [name] : value에서 []를 사용한 이유는 객체의 key 값을 동적으로 할당하기 위해서이다. 
                   [name]은 name의 변수, 즉 title과 contents를 불러온다.

 

 

댓글