리액트

24. 05. 28 TIL (props-drilling-2)

효ㄷi 2024. 5. 28. 20:54

4. InputForm 파일

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

밑의 uuid는 id를 생성해주는 라이브러리다.

설치 후 저렇게 넣어준다.

 

이제 어떻게 하지...........

 

라고 하지 말고 먼저 생각을 해본다.

 

일단 상단 인풋 값을 입력하는 디자인을 먼저 짜보자.

 

그럼 폼 태그 내부에 각 항목을 넣어서 디자인 해본다.

 

4번으로 이동.

 

1.

const InputForm = ({ setItemList, MonthSaveFunc }) => {
  const [dateValue, setDateValue] = useState('');
  const [itemValue, setItemValue] = useState('');
  const [amountValue, setAmountValue] = useState('');
  const [descriptionValue, setDescriptionValue] = useState('');

자... 이제 useState를 만들어주는데, 각각 인풋창에 맞게 4개 만들어 준다.

초기값은 빈 값이다. 이제 onChange에 들어가는 함수를 입력해주자.

 

그리고 setItemList와 MonthSaveFunc를 받아오는 걸 기억하자.

2번으로 이동.

 

 

2.

  const inputDatefunc = (e) => {
    setDateValue(e.target.value);
  };
  const inputItemfunc = (e) => {
    setItemValue(e.target.value);
  };
  const inputAmountfunc = (e) => {
    setAmountValue(e.target.value);
  };
  const inputDescriptionfunc = (e) => {
    setDescriptionValue(e.target.value);
  };

자 이제 각 인풋 창에서 함수를 실행해서 변경된 값을 set~에 넣어주는 것이다.

그럼 dateValue의 값들이 업데이트 될 듯.

 

이제 submit 함수를 만들어 본다. 3번으로 이동.

 

3.

  const submitForm = (e) => {
    e.preventDefault();

    const newItem = {
      date: dateValue,
      item: itemValue,
      amount: amountValue,
      description: descriptionValue,
      id: uuidv4(),
    };

    const date = parseInt(newItem.date.slice(6, 7));
    MonthSaveFunc(date);

    if (dateValue && itemValue && amountValue && descriptionValue !== '') {
      setItemList((prev) => [...prev, newItem]);
      setDateValue('');
      setItemValue('');
      setAmountValue('');
      setDescriptionValue('');
    } else {
      alert('값을 모두 입력해주세요');
    }
  };

onSubmit을 할 때 실행되는 함수를 만드는 것이다.

이 함수의 역할은 값을 모아서 리스트로 출력해준다.

일단 폼은 새로고침 되므로 e.preventDefault로 일단 막자.

그리고 이걸 보여줘야 할 것이 아닌가?

리스트에 추가하기 위해 객체로 만든다.

 

이 객체엔 value에 있던 업데이트된 현재 인풋값을 넣어준다.

또 id는 각 항목을 고유하게 식별하기 위해서 uuid를 사용해 넣어준다.

 

일단 newItem 객체에서 달을 뽑아 MonthSaveFunc 함수에 전달한다.

이건 사용자가 입력한 date에서 달을 뽑아 전달하고, 그 달을 화면에 표시하도록 하는 목적인 걸로 기억한다.

 

이제 각 dateValue 등 현재 업데이트 된 값이 비어있나 확인한다. 하나라도 비어있으면 조건문이 실행되지 않는다.

비어있지 않으면 setItemList에서 매개변수로 prev(이전 항목?)을 받아오고,

스프레드 연산자로 prev를 복사한 뒤 newItem을 붙인다. 

그럼 불변성을 유지하면서 상태를 업데이트 한다.

 

그리고 값이 비어있다면 alert를 띄운다.

 

 

 

4.

  return (
    <>
      <form onSubmit={submitForm}>
        <div>
          <label htmlFor="date">날짜</label>
          <input type="date" id="date" onChange={inputDatefunc} value={dateValue} />
        </div>
        <div>
          <label htmlFor="item">항목</label>
          <input type="text" id="item" placeholder="지출 항목" onChange={inputItemfunc} value={itemValue} />
        </div>
        <div>
          <label htmlFor="amount">금액</label>
          <input type="number" id="amount" placeholder="지출 금액" onChange={inputAmountfunc} value={amountValue} />
        </div>
        <div>
          <label htmlFor="description">내용</label>
          <input type="text" id="description" placeholder="지출 내용" onChange={inputDescriptionfunc} value={descriptionValue} />
        </div>
        <button type="submit">저장</button>
      </form>
    </>
  );
};

label 태그는 저 항목이라는 글씨를 보여준다.

htmlFor=date는 input의 id와 연결해준다.

그래서 라벨 태그를 클릭해도 인풋창에 커서가 가게 된다.

 

이걸 각각 작성해서 폼태그 내부에 넣는데,

폼 태그는 이 여러 입력 요소를 모아서 제출할 수 있게 해준다.

 

그리고 버튼의 type submit은 폼의 데이터가 서버로 제출될 수 있도록 한다.

onSubmit은 폼이 제출될 때 실행할 함수를 정한다.

즉, 인풋값을 입력 후 폼을 제출하면 onSubmit의 함수가 실행된다.

 

일단 입력값을 어떻게 가져오는지부터 알아보자.

 

일단 각각 인풋에 onChange와  value를 입력해 줘야 한다.

onChange는 값이 입력, 지워질 때마다 실행되는 이벤트다.

value는 말 그대로 인풋창에 어떤 값이 들어있는지 정해준다.

내가 1을 value에 입력하면 value는 1로 고정된다.

 

value에 dataValue를 넣어주면 인풋창의 값이 항상 dateValue와 일치하게 된다.

 

이제 1번으로 이동.


5. MonthBtn 파일

 

이 파일은 달 버튼을 만드는 파일이다.

 

먼저 달을 만드려면 배열을 만들어주자.

const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

 

그리고 일단 2번으로 간다.

const MonthBtn = ({ MonthSaveFunc }) => {

MonthSaveFunc 함수를 받아오는데 이 함수는 라우터에 있는 함수다.

 

올리기 귀찮으니까 

const MonthSaveFunc = (month) => {
    setSaveMonth(month);
    localStorage.setItem('month', month);
  };

이렇게 생겼다. 일단 더 봐보자.

 

자 보면 MonthSaveFunc 함수가 실행되어 month를 받아와 setSaveMonth에 주고 있다.

(이 setSaveMonth는 라우터에 작성되었다.)

 

로컬 스토리지는 이 클릭한 달을 받아서 저장한다. 이 저장한 것은 마지막에 클릭한 달을 저장하는 건데

다시 가져와서 

 const [saveMonth, setSaveMonth] = useState(lastMonth);

여기 넣어주면 초기값으로 마지막으로 클릭한 달을 가져온다.

 

2.

{months.map((month, index) => {
            return (
              <Button
                key={index}
                onClick={() => {
                  MonthSaveFunc(month);
                }}
              >
                {month}월
              </Button>
            );
          })}

먼저 배열에 있는 숫자를 꺼내려면 map을 돌려야 한다.

months 배열에서 요소 하나하나인 month를 키로 index를 주어 돌린다.

그리고 돌리면서 달 버튼을 뱉어낸다.

 

그리고 이 버튼을 클릭하면? MonthSaveFunc 함수에 month가 전달되어 실행된다.

다시 위로 가볼까...