DEVELOP
article thumbnail

인프런 이정한님의 한입크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 ] 강의 수강 후 강의의 내용을 정리하며 공부한 것을 쓴 게시글입니다.

 

한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 - 인프런 | 강의

개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, - 강의 소개 | 인프런...

www.inflearn.com


삭제 기능 구현

- 일기 아이템 클릭 후 수정하기 페이지에서 삭제 기능 구현

- 추후 홈 화면에서도 삭제 가능하도록 구현할 예정

- diaryEditor의 헤더의 rightChild에 삭제 버튼 추가

- 새 일기 쓸 때에는 삭제 기능이 구현되면 안되므로 isEdit이 참일 때만 버튼 보이게 함 

          rightChild={
            isEdit && (<MyButton text={"삭제"} type={"negative"} onClick={handleRemove}/>)
          }

- onClick 함수인 handleRemove 함수 정의

  const handleRemove = () => {
    if (window.confirm("일기를 삭제할까요?")) {
      onRemove(originData.id);
      navigate("/", { replace: true });
    }
  };


LocalStorage 사용하기

LocalStorage 사용 예제

- LocalStorage에 데이터 저장하기 

  - localStorage.setItem("key", value);

  - 객체 그대로를 전달하면 원하는 대로 값이 전달되지 않으므로, JSON의 stringify함수를 이용해서 객체를 저장

    localStorage.setItem("item1", 10);
    localStorage.setItem("item2", "10");
    localStorage.setItem("item3", { value: 30 });
    localStorage.setItem("item4", JSON.stringify({ value: 30 }));

- LocalStorage의 데이터 가져오기

  - key값으로 데이터를 가져올 수 있음 

  - const item = localStorage.getItem("key");

    const item1 = localStorage.getItem("item1");
    const item2 = localStorage.getItem("item2");
    const item3 = localStorage.getItem("item3");
    const item4 = localStorage.getItem("item4");

- 정수를 저장해도 가져올 때는 문자열 형태로 가져오게 됨

- JSON으로 저장한 객체 타입도 문자열 형태로 가져오게 됨

- 정수형 그대로 가져오려면 parseInt 써야하고, 객체를 그대로 가져오려면 JSON.parse 써야 함 

    const item1 = parseInt(localStorage.getItem("item1"));
    const item2 = localStorage.getItem("item2");
    const item3 = localStorage.getItem("item3");
    const item4 = JSON.parse(localStorage.getItem("item4"));


LocalStorage에 Diary 저장하기

- app.js의 reducer 함수에 newState를 key값을 diary로 하여 localStorage에 저장

  localStorage.setItem("diary", JSON.stringify(newState));

LocalStorage에서 Diary 가져오기 

- 컴포넌트가 mount 될 때 실행되도록 useEffect 사용 

- key값인 diary로 getItem해서 localData에 저장 

- localData가 있고, 길이가 0보다 클 때만 가져온 값을 diaryList에 저장

- 현재 데이터들의 아이디 값을 내림차순으로 정렬했을 때, 아이디가 가장 큰 값인 첫번째 요소의 아이디값에 1을 추가한 것을 그 다음 추가될 요소의 아이디인 dataId로 지정함 

- dispatch함수에 type을 INIT으로 하여 dairyList를 저장

  const [data, dispatch] = useReducer(reducer, []);
  useEffect(() => {
    const localData = localStorage.getItem("diary");
    if (localData && JSON.parse(localData).length > 0) {
      const diaryList = JSON.parse(localData).sort(
        (a, b) => parseInt(a.id) - parseInt(b.id)
      );
      console.log(diaryList);
      dataId.current = parseInt(diaryList[0].id) + 1;
      dispatch({ type: "INIT", data: diaryList });
    }
  }, []);

localStorage에 정상적으로 저장되며 모든 기능 정상 작동


프로젝트 최적화하기

문제점1. 월 이동시마다 ControlMenu가 리렌더링 됨 

-> ConrolMenu 함수를 React.memo로 감싸줌 

const ControlMenu = React.memo(({ value, onChange, optionList }) => {
  return (
    <select className="ControlMenu" value={value} onChange={(e) => onChange(e.target.value)}>
      {optionList.map((it, idx) => (
        <option key={idx} value={it.value}>{it.name}</option>
      ))}
    </select>
  );

 

문제점2. ConrolMenu 변경할때마다 (최신순/오래된 순 변경) DiaryItem들이 리렌더링 됨

-> DiaryItem을 export할 때 React.memo로 감싸줌

export default React.memo(DiaryItem);

 

문제점3. 일기의 내용 수정할때마다 그 위에 있는 EmotionItem들이 리렌더링 됨

-> EmotionItem을 export할 때 React.memo로 감싸줌 

-> handleClickEmotion함수를 useCallback으로 감싸줌

export default React.memo(EmotionItem);
  const handleClickEmotion = useCallback((emotion) => {
    setEmotion(emotion);
  }, []);

배포 준비 & 프로젝트 빌드하기

icon 변경하기 

- 무료 다이어리 아이콘 png 파일을 다운받고, ico 파일로 변경함

&lt;a href=&quot;https://www.flaticon.com/kr/free-icons/&quot; title=&quot;일기 아이콘&quot;&gt;일기 아이콘 제작자: Freepik - Flaticon&lt;/a&gt;

title 변경하기

- title 태그를 받아와서 innerHTML을 변경해주면 된다.

- 다이어리 상세보기 페이지에서는 해당 일기의 날짜를 title에 반영하고 싶어서 아래와 같이 코드를 썼다.

  useEffect(() => {
    const titleElement = document.getElementsByTagName("title")[0];
    titleElement.innerHTML = `Emotion Dairy`;
  });
      if (targetDiary) {
        setData(targetDiary);
        const titleElement = document.getElementsByTagName("title")[0];
        titleElement.innerHTML = `${moment(targetDiary.date).format(
          "MM월 DD일 dddd"
        )} - Emotion Dairy`;
      }

title

빌드하기

- 빌드 명령어 (cmd) 

$ npm run build
$ npm install -g serve (serve 설치 안되어 있다면)
$ serve -s build

- 아래와 같이 뜨면 빌드 완료 

- 만약 오류를 발견해 수정이 필요하면 수정 후 위 명령어를 다시 입력 

- npm start를 하지 않아도 아래 주소에 접속 가능 

- Network에 있는 주소는 현재 내 pc와 같은 네트워크와 연결되어 있는 곳에서 접속 가능


Firebase로 프로젝트 배포하기

 

Firebase

Firebase는 고품질 앱을 빠르게 개발하고 비즈니스를 성장시키는 데 도움이 되는 Google의 모바일 플랫폼입니다.

firebase.google.com

1.  파이어베이스 접속해 로그인

2. 메인 화면에서 시작하기 클릭

3. 프로젝트 추가 클릭 

4. 프로젝트 이름을 입력하고 '계속' 버튼 클릭

5. 이 프로젝트에서 Google 애널리틱스 사용 설정 체크 해제하고, (필요시 체크) 프로젝트 시작 버튼 클릭

6. 왼쪽 메뉴에서 빌드 - 호스팅 - 시작하기

7. cmd에서 $ npm install -g firebase-tools입력

8. vs코드의 루트 프로젝트 폴더 로 가서 cmd터미널에서  $ firebase login 입력

9. y입력하고, 계정 선택하면 로그인 성공 창 팝업됨 

9. $ firebase init 입력 

10. y입력 -> Hosting 선택 -> Use an existing project 선택 -> 프로젝트 선택 -> build 입력 -> y입력 -> 깃허브 사용 시 y입력 -> y입력 

11. 파이어베이스 사이트로 다시 들어와서 콘솔로 이동 버튼 클릭 

12. 맨 아래로 내려가서 고급 - 다른 사이트 추가 - 만들고자 하는 페이지 url 지정

13. firebase.json 파일에서 "hosting" 안 "site" 지정해줌

  "hosting": {
    "site": "cjy00n-emotion-diary",
    "public": "build",

14. 다시 $npm run build 

15. $ firebase deploy

16. 접속 가능


- 썸네일 이미지, 사이트 이름, 사이트 설명 설정하기

- 아래코드를 index.html 파일에 쓴다.

    <meta property="og:image" content="%PUBLIC_URL%/thumbnail.png" />
    <meta property="og:site_name" content="Emotion Dairy" />
    <meta property="og:description" content="What's your today emotion?" />

- $ npm run build 

- $ firebase depoly 

- 이전에 한 번 공유하고, 다시 공유한다면, 카카오톡에서 공유했을 때, 바뀐 것들이 적용되지 않는다. 

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

- 도구 - 디버거 도구 - 공유 디버거 - url 입력창에 url 입력 후 캐시 초기화 클릭

- 아래와 같이 썸네일과 설명, 사이트 이름이 잘 적용되었다.

- 나중에 기능을 더 추가하여 디자인 된 썸네일을 다시 등록할 예정이다. 

 

Emotion Diary

What's your today emotion?

cjy00n-emotion-diary.web.app

 

profile

DEVELOP

@JUNGY00N