개인프로젝트: Todo 리스트 만들기(2)

윤뿔소·2022년 12월 11일
0

프로젝트

목록 보기
4/4

이번에는 초기 기획했던 것처럼 날짜를 골라 날짜에 맞는 데이터를 서버에서 로드, 세이브할 수 있게 해보자.

사용 라이브러리

달력 관련: react-calendar, moment

Header

위 기획했던 대로 클릭시 나오는 달력과 달력의 날짜를 가져와 헤더에 부착하고 헤더를 누르면 달력이 뜨게끔 구현해보겠다.
근데 클릭하여 나오게 만드는 것보다 그냥 바로 보여주고 어떤 날에 일일 과제가 있었는지 보여주는 게 더 나을까?

일단 날짜를 보여주고, 달력을 가지기 위해 설치할 것들을 설치하자

npm i moment
npm i react-calendar

그리고 공식페이지에서 공식과 결과물을 가져오기 위해 moment를 쓴 결과는?

import "./App.css";
import React, { useState } from "react";
import Calendar from "react-calendar";
import moment from "moment";
import "react-calendar/dist/Calendar.css";
// 따로 css 하고 싶다면 파일 코드를 그대로 가져와 Styled Component 하면 된다.

function App() {
  const [value, onChange] = useState(new Date());
  return (
    <div className="App">
      <Calendar onChange={onChange} value={value} />
      <div className="text-gray-500 mt-4">{moment(value).format("YYYY년 MM월 DD일")}</div>
    </div>
  );
}
export default App;

요로케 나온다. 나중에 css로 조작하여 이쁘게 잡아보자. 이제 헤더를 만들 차례다.
모달처럼 만들어서 헤더를 누르면 달력이 나오게끔 만들었다.

문제: 이벤트버블링

  1. 하나의 컴포넌트인 header 안에 모달로 나오는 달력과 나타내는 날짜를 같이 써도 될까? 리액트는 하나의 컴포넌트 당 하나의 기능을 넣어야하는데, 이 기능이 하나로 되는지 두개로 나뉘는 지 모르겠다.. 일단은 다 넣는데 리팩토링 과정에서 나뉘어야한다고 치면 상태관리 라이브러리 써서 쪼개보자
  2. 아니 이벤트 버블링 이거 어떡하지
<>
  <HeaderContainer onClick={modalHandler}>
    <DayToYear>{moment(value).format("YYYY년 MM월 DD일")}</DayToYear>
    <DayOfWeek>{moment(value).format("dddd")}</DayOfWeek>
  </HeaderContainer>
  <ModalContainer>
    {isModalOpen && (
      <ModalBackdrop onClick={modalHandler}>
        <Calendar onChange={onChange} value={value} />
      </ModalBackdrop>
    )}
  </ModalContainer>
</>

stopPropagation()써도 안된다.. 이거 아마 달력을 따로 페이지로 나누든가 달력 버튼을 따로 만들던가 아니면 이벤트 버블링을 따로 어떻게 해결해야하는데.. 아고라스테이츠에 물어봐야겠다.

쨌든 모달로는 구현 했다..

import React, { useState } from "react";
import Calendar from "react-calendar";
import moment from "moment";
import "./Calendar.css"; // css import
import styled from "styled-components";

const HeaderContainer = styled.div`
  display: flex;
  justify-content: center;
  flex-direction: column;
  position: relative;
  cursor: pointer;
  border-bottom: 1px solid #0f4c75;
  height: 96px;
`;
const DayToYear = styled.div`
  font-size: 30px;
  margin: auto;
`;
const DayOfWeek = styled.div`
  font-size: 25px;
  margin: auto auto 13px;
  color: #bbe1fa;
`;
const ModalContainer = styled.div`
  margin: auto;
  position: relative;
  z-index: 2;
`;
const ModalBackdrop = styled.div`
  // Modal이 떴을 때의 배경을 깔아주는 CSS를 구현
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.5);
`;

const Header = () => {
  // 캘린더 상태값
  const [value, onChange] = useState(new Date());
  // 모달 노출 상태값
  const [isModalOpen, setIsModalOpen] = useState(false);
  const modalHandler = (e) => {
    setIsModalOpen(!isModalOpen);
  };

  return (
    <>
      <HeaderContainer onClick={modalHandler}>
        <DayToYear>{moment(value).format("YYYY년 MM월 DD일")}</DayToYear>
        <DayOfWeek>{moment(value).format("dddd")}</DayOfWeek>
      </HeaderContainer>
      <ModalContainer>
        {isModalOpen && (
          <ModalBackdrop onClick={modalHandler}>
            <Calendar onChange={onChange} value={value} />
          </ModalBackdrop>
        )}
      </ModalContainer>
    </>
  );
};

export default Header;

https://user-images.githubusercontent.com/94962427/205480495-de93000d-2c35-4ce6-8af7-ac7e0ae90ebd.mov

2022/12/10 해결!!!

해결했다! useEffect를 써서 value가 변할 때마다 리렌더링돼 중첩을 피하고도 결괏값을 도출해낼 수 있었다!

...
// 모달 노출 상태값
const [isModalOpen, setIsModalOpen] = useState(false);
const modalHandler = (e) => {
  setIsModalOpen(true);
};
// useEffect에 달력 값이 변하면 setIsModalOpen가 false가 되고 달력 값을 그대로 전달하게
useEffect(() => {
  setIsModalOpen(false);
}, [value]);

return (
  <>
    <HeaderContainer onClick={modalHandler}>
      <DayToYear>{moment(value).format("YYYY년 MM월 DD일")}</DayToYear>
      <DayOfWeek>{moment(value).format("dddd")}</DayOfWeek>
    </HeaderContainer>
    <ModalContainer>
      {isModalOpen && (
        <ModalBackdrop>
          <Calendar onChange={onChange} value={value} />
        </ModalBackdrop>
      )}
    </ModalContainer>
  </>
);

!isModalOpen 대신 true, false로 한가지 기능한 하게 만들었고, value를 디펜던시로 넣어서 변할 때마다 리렌더링되게 했고, 실행되면 setIsModalOpenfalse가 되게 하니 됐다!

문제: 날짜마다 새긴 각 리스트데이터를 어떻게 불러올까?

어떻게 불러오지..

profile
코뿔소처럼 저돌적으로

0개의 댓글