Notice
Recent Posts
Recent Comments
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

AI기록장

React_기초다지기_하루정리(new Date(), sortType-Compare, 이미지를 이용한 마크업) 본문

React

React_기초다지기_하루정리(new Date(), sortType-Compare, 이미지를 이용한 마크업)

SanL 2023. 6. 5. 00:15

◼︎React


⚑목표 : 홈페이지 구현


↓홈페이지 구현 중 내가 기억하고 싶은 개념정리

[new Date를 사용한 응용]

  • new Date로 생성된 시간은 해당 년도와 해당 달 등 세분화하여 출력할 수 있음
    // .getFullYear(): 년 , .getMonth() : 달(1을 더해주어야 12월까지표현할 수 잇음 주의!)

[Home.js]

import { useState } from "react";

import MyHeader from "./../components/MyHeader";

const Home = () => {
  const [curDate, setCurDate] = useState(new Date());

  const headText = `${curDate.getFullYear()}년 ${curDate.getMonth() + 1}월`;

  return (
    <div>
      <MyHeader headText={headText} />
    </div>
  );
};
export default Home;  
  • 만약 내가 버튼을 눌렀을 때, 달이+1 되거나 -1되고 싶게 하고 싶다면, setCurDate를 +1된 달로 변환시켜주고,
    -1된 달로 변환시켜주어 클릭시 변환하도록 변경하면된다!

[Home.js / increase,decrease]

  const increaseMonth = () => {
    setCurDate(
      new Date(curDate.getFullYear(), curDate.getMonth() + 1, curDate.getDate())
    );
  };

  const decreaseMonth = () => {
    setCurDate(
      new Date(curDate.getFullYear(), curDate.getMonth() - 1, curDate.getDate())
    );
  };

만약 내가 일정 기간내의 데이터를 뽑아 내고 싶을 때 어떻게 해야할까?

const Home = () => {
  const dairyList = useContext(DiaryStateContext);

  const [data, setData] = useState([]);
  const [curDate, setCurDate] = useState(new Date());
  const headText = `${curDate.getFullYear()}년 ${curDate.getMonth() + 1}월`;

  //해당 달안에 있는 dairyList를 출력함, 1일부터 31일의 범위에서 dairyList에 저장된 부분을 뽑아냄
  useEffect(() => {
    if (dairyList.length >= 1) { // dairyList가 비어있을 때는 필요없음
      const firstDay = new Date(
        curDate.getFullYear(),
        curDate.getMonth(),
        1
      ).getTime();

      const lastDay = new Date(
        curDate.getFullYear(),
        curDate.getMonth() + 1
      ).getTime();

      setData(
        dairyList.filter((it) => firstDay <= it.date && it.date <= lastDay)
      );
    }
  }, [dairyList, curDate]);

  useEffect(() => {
    console.log(data);
  }, [data]);
  • 우선적으로, 일기의 내용들이 저장되어있는 것은 diaryList이고, 이 안에 저장된 날짜의 범위를 설정해주고,
    그 사이의 날짜를 filter을 이용해서 data의 상태를 변환해주면된다!
    // 내가 생각했을 떄는 diary가 각각의 달에 어디에 저장되었는지를 생각해보는 것이 중요하고,
    그 데이터를 또 어디에 저장하는지 관계를 이해하는 것이 중요한거같다.
    그래야 상태변환을 사용할 때 각각의 상태를 정확하게 이용할 수 있을꺼같다.


[데이터들을 시간순대로 정리하려면?]

  • 우리는 어떠한 데이터가 들어왔을 때, 최신순으로, 오래된 순으로 보고싶을 경우가 있는데,
    이럴떄는 어떠한 접근방식을 가져야할까?

[DiaryList.js]

const sortOptionList = [
  { value: "latest", name: "최신순" },
  { value: "oldest", name: "오래된 순" },
];

const ControlMenu = ({ value, onChange, optionList }) => {
  return (
    <select value={value} onChange={(e) => onChange(e.target.value)}>
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>
          {it.name}
        </option>
      ))}
    </select>
  );
};
  • 우선적으로는, 내가 시간순에 따라 데이터 리스트들을 나열하려면, 내가 옵션을 정해주고, 그 값들이 어떻게 변할지 생각해줘야한다.
    즉, 위 코드처럼, 최신순과 오래된 순으로 옵션을 정리해주고, 값은 오래되었을 때와, 최신의 값으로 각각 정렬 할 수 있도록
    주고, 그 값들이 변화된다면, 값을 상태변화시켜주면되는 것이다.

그러면 데이터들을 내가 최신순과 오래된 순으로 나열하려면 각각의 데이터들을 비교해줘야한다.

[DiaryList.js]


const DiaryList = ({ diaryList }) => {
  const [sortType, setSortType] = useState("lastest");

  //배열을 제이쓴화 시켜서 문자열로 만들어주고 parse해주면 다시 배열로 바뀜
  //최신순인지 오래된 순인지 비교해줌
  const getProcessedDiaryList = () => {
    const compare = (a, b) => {
      if (sortType === "latest") {
        return parseInt(b.date) - parseInt(a.date);
      } else {
        return parseInt(a.date) - parseInt(b.date);
      }
    };

    const copyList = JSON.parse(JSON.stringify(diaryList));
    const sortedList = copyList.sort(compare);
    return sortedList;
  };

  return (
    <div>
      <ControlMenu
        value={sortType}
        onChange={setSortType}
        optionList={sortOptionList}
      />
      {getProcessedDiaryList().map((it) => (
        <div key={it.id}>{it.content}</div>
      ))}
    </div>
  );
};
  • getProcessedDiaryList함수를 통해서 값을 오래되었을 떄와 최신순일떄는 비교해주게된다.

//copuList변수를 보면 배열을 제이쓴화 시켜서 문자열로 만들어주고 parse해주면 다시 배열로 바꿔주는 것


[useNavigate]

  • 리액트의 라우터를 이용하여, 특정 컴퍼넌트로 이동할 수 있게 도와준다!
import { useNavigate } from "react-router-dom";

.
.
.
 <MyButton
        type={"positive"}
        text={"새 일기 쓰기"}
        onClick={() => navigate("/new")}
 />
  • 위와 같이 사용하면 클릭 시 new컴퍼넌트로 이동할 수 있다.
    // 간단하지만, 헷갈릴 수 있는 부분이니 기억해두자

[이미지 파일 가져오기!]

  • 만약 내가 각각의 이미지 마다 어떤 기준을 두고, 그 기준에 따라, 출력하고 싶다면, 어떻게해야할까?
 <div
        onClick={goDetail}
        className={[
          "emotion_img_wrapper",
          `emotion_img_wrapper_${emotion}`,
        ].join(" ")}>
        <img src={process.env.PUBLIC_ULR + `assets/emotion${emotion}.png`} />
    </div>
  • 위 코드에서 img 부분을 보면 나는 각각의 파일 이름을 현재 emotion 1,2,3 -- 이런형식으로 저장해두었고,
    각각의 기분에 따라, 그 기분에 맞는 이미지 파일을 랜더링할 수 있도록 ${emotion}으로 주어, 단지 이미지를
    출력하는 것이 아니라, 각 이미지 파일에 직접접근했다 !

[DiaryItem.js]

import { useNavigate } from "react-router-dom";
import MyButton from "./MyButton";

const DiaryItem = ({ id, emotion, content, date }) => {
  const navigate = useNavigate();

  const goDetail = () => {
    navigate(`/diary/${id}`);
  };

  const goEdit = () => {
    navigate(`/edit/${id}`);
  };

  const env = process.env;
  env.PUBLIC_URL = env.PUBLIC_URL || "";

  const strDate = new Date(parseInt(date)).toLocaleDateString();

  return (
    <div className="DiaryItem">
      <div
        onClick={goDetail}
        className={[
          "emotion_img_wrapper",
          `emotion_img_wrapper_${emotion}`,
        ].join(" ")}>
        <img src={process.env.PUBLIC_ULR + `assets/emotion${emotion}.png`} />
      </div>
      <div onClick={goDetail} className="info_wrapper">
        <div className="diary_date">{strDate}</div>
        <div className="diary_content_preview">{content.slice(0, 25)}</div>
      </div>
      <div className="btn_wrapper">
        <MyButton onClick={goEdit} text={"수정하기"} />
      </div>
    </div>
  );
};

export default DiaryItem;
  • 각각의 이미지에 따라 알맞는 마크업을 통해 기능적부분 추가!