React - Local Storage로 만드는 최근 본 상품기능

신혜원·2023년 7월 29일
0

React

목록 보기
36/37
post-thumbnail
post-custom-banner
  • 새로고침을 하면 모든 state 데이터는 리셋이 된다.
    그 이유는 새로고침하면 브라우저는 html, css, js 파일들을 처음부터 다시 읽기 때문이다.
  • 이게 싫다면 state 데이터를 서버로 보내서 DB에 저장하면 된다.
  • 서버나 DB에 대해 잘 모른다면 localStorage를 이용해도 된다.

  • 크롬개발자 도구에서 Application 탭 들어가면 있다.
    -사이즈마다 5MB 정도의 문자 데이터를 저장할 수 있다.
    -object 자료랑 비슷하게 key/value 형태로 저장한다.
    -유저가 브라우저를 청소하지 않는 이상 영구적으로 남아있다.

🖤 localStorage 문법

  • 아무 js 파일에서 문법을 쓰면 localStorage에 데이터를 입출력 할 수 있다.
localStorage.setItem('데이터이름', '데이터'); // 데이터를 추가한다.
localStorage.getItem('데이터이름'); // 데이터를 읽는다.
localStorage.removeItem('데이터이름'); // 데이터를 삭제한다.

🖤 localStorage에 array / object 자료를 저장하기

  • localStorage는 문자만 저장할 수 있는 공간이라 array/object를 바로 저장할 수는 없다.
  • 강제로 저장해보면 문자로 바꿔서 저장하는데 그렇게 되면 array/object 자료가 깨져서 저장이 된다.
  • 그래서 array/object -> JSON 으로 변환해서 저장하면 array/object 자료를 저장할 수 있다.
    JSON은 문자취급을 받기 때문이다. (just 따옴표 친 array/object 자료)
localStorage.setItem('obj', JSON.stringify({name:'kim'}) );
  • JSON.stringify() 라는 함수에 array/object를 집어넣으면 그 자리에 JSON으로 변환된 것을 남겨준다.
var a = localStorage.getItem('obj');
var b = JSON.parse(a)
  • 당연히 데이터를 꺼내면 JSON 이 나오고
    JSON -> array/object 를 변환하고 싶다면 JSON.parse() 를 사용하면 된다.


🖤 최근 본 상품 UI 기능 만들기

  • 메인페이지에 최근 본 상품을 보여주는 아주 성가신! UI 만들기
  • 사이트를 재접속해도 잘 보여야하기 때문에 localStorage를 활용하면 된다.

📒오늘의 숙제

: 상세페이지에 들어가면 현재 페이지에 있는 상품 id를 localStorage에 저장되게 만들기

  • 저장할 땐 array 자료형을 활용하면 된다.
  • 만약 0번, 1번 상품을 보았다면 [0, 1] 이런 데이터가 localStorage에 저장되게 만들면 된다.
  • 누가 사이트로 접속 시 localStorage에 [] 가 하나 있어야 자료 추가가 쉽다.
function App() {

  useEffect(()=>{
    localStorage.setItem('watched', JSON.stringify( [] ))
  },[]) 

}

  • 우선 숙제를 하기에 앞서 강의에 나왔던 것처럼 홈 화면을 클릭하면 상세페이지로 이동하게 만들 것이다.
function Card(props) {
  let navigate = useNavigate();
  return (
    <>
      <Col>
        <img
          src={"https://codingapple1.github.io/shop/shoes" + props.i + ".jpg"}
          width="80%"
          onClick={() => {
            navigate(`/detail/${props.i - 1}`);
          }}
        ></img>
        <h4>{props.shoes.title}</h4>
        <p>{props.shoes.price}</p>
      </Col>
    </>
  );
}
  • 그리고 상세페이지에서 이미지가 바뀌지 않은 것도 해결했다...ㅜㅜ
<div className="col-md-6">
  <img src={`https://codingapple1.github.io/shop/shoes${result.id + 1}.jpg`}
       width="100%"
  />
</div>
  • 처음에는 이미지 경로에 ...shoes${result} 를 썼는데 사진이 자꾸 뜨지 않았다.
    그래서 오류를 읽어보니 이미지 경로에 object 가 들어있었다.
  • result 는 data에서 하나의 object를 뜻하는 것이므로 우리가 원하는 데이터를 뽑아내기 위해서는 key를 입력해야했다.

  • 짜야할 코드를 자세히 읽어보니
    상세페이지 들어가면 "현재 페이지에 있는 상품 id를 localStorage에 저장되게 만들기기"
    즉, result.id 를 localStorage에 저장하면 되는 것이다!!
(Detail.js)

localStorage.setItem("watched", [id]);
  • 그래서 Detail.js 에서 저장해보니 2초 후에 꺼지는 이벤트 alert 가 끝나야 자료가 저장이 된다. (알고보니 이건 타이머 이벤트 밑에 적어서!!)
    하지만 이것도 array형이 아닌 그냥 숫자만...
(Detail.js)

  useEffect(() => {
    let watchArr = localStorage.getItem("watched");
    watchArr = JSON.parse(watchArr);
    watchArr.push(id);
    watchArr = new Set(watchArr);
    watchArr = Array.from(watchArr);
    localStorage.setItem("watched", JSON.stringify(watchArr));
  });
  1. 상세페이지에 접속하면 ( Detail 컴포넌트가 로딩되면)
  2. localStorage의 데이터를 꺼내 watchArr 이라는 변수에 저장한다.
  3. watchArr 에 id 값을 넣는다.
  4. 중복된 데이터를 넣지 않는 set 자료형에 watchArr을 담아 중복을 제거한다.
  5. 중복제거된 set 자료형의 watchArr을 일반 배열로 변경한다.
  6. localStorage에 데이터를 JSON 자료형으로 저장한다.
  • 작동이 원활하지가 않다...🥲

  • 새로고침을 한 직후에는 바로 저장이 되지만 다른 창을 다녀오면 작동도 되지 않고 localStorage에 값도 저장 되지 않는다.

🚨 도와줘요 선생님...!

1. 누가 Detail 페이지에 접속하면
2. 현재 페이지에 보이는 상품 id를 가져와서
3. localStorage에 watch 항목에 있던 [] 에 추가해주세요.
  • 이렇게 한글로 짜고 그대로 JS 번역을 하면 된다.

📗 useEffect() 사용법

  • 기본형태 : useEffect (function, deps)
    function : 수행하고자 하는 작업
    deps : 배열형태이며 배열 안에는 검사하고자 하는 특정 값 or 빈 배열을 집어넣는다.
  • useEffect 는 어떤 값의 변화가 감지되면 실행되어
    특정 함수나 작업을 실행하는 함수이다.
  • 렌더링이 끝나면 무조건 한 번은 useEffect 가 실행된다.
  • useEffect 에 대괄호[] 를 사용하면, 렌더링 후 무조건 단 한 번만 실행된 후 더이상 실행되지 않는다.
  • deps 자리에 변수를 지정하게 되면 다른 값과 상관 없이
    지정된 값이 변해야만 useEffect() 가 실행된다.
(Detail.js)
let result = props.shoes.find((x) => x.id == id);
...
useEffect(()=>{
  console.log(result.id)
}, [])
  • 1번, 2번은 이렇게 하면 된다.
  • Detail.js 아무데나 useEffect() 하나 집어 넣으면 1번 번역 끝이고
    2번은 예전에 만들었던 result 값의 id를 출력하면 끝난다.
  • 이제 3번 localStorage에 watch 항목을 추가하는 것은
    localStorage에 있던 기존 데이터를 수정하는 것은 불가능하다고 했다. (입력/출력 만 가능하다.)

  • 즉 수정하려면 watch에 있던 [] 를 빼서 result.id를 추가하고
    다시 watch 항목으로 저장하는 식으로 코드를 짜야한다.

  • 역시나 강의에서 방법은 같지만 내 코드에 문제가 있는 것 같다.
  • 💡 메인 페이지 방문 시 localStorage를 [] 로 설정하라는 것을 지웠더니 해결이 됐다.

🖤 중복제거하기

  • "상품 id가 이미 [] 에 있으면 추가하지 말아주세요" 라고 추가를 하면 된다.
  • Set 자료형 사용하기
    Set 은 array와 똑같은데 중복을 알아서 제거해주는 array 이다.
  • array -> Set -> array 이런식으로 쓰면 array 에서 중복제거를 쉽게 할 수 있다.
  useEffect(() => {
    let watchedArr = localStorage.getItem("watched");
    watchedArr = JSON.parse(watchedArr);
    watchedArr.push(result.id);
    // Set 으로 바꿨다가
    watchedArr = new Set(watchedArr);
    // 다시 array 로 변환했다.
    watchedArr = Array.from(watchedArr);
    localStorage.setItem("watched", JSON.stringify(watchedArr));
  }, []);

🖤 응용사항

  • 사이트 새로고침 시 localStorage에 있던 항목도 싹 [] 이렇게 비워지는데 그 이유는 App 컴포넌트 로드 시 [] 이걸 새로 넣으라고 코드를 짰기 때문이다.
  • 그래서 if문을 사용해 localStorage에 watched항목이 있으면 [] 이걸 새로 넣지 말아주세요 라는 코드를 짰다.
function App() {
  useEffect(() => {
    let watchedArr = localStorage.getItem("watched");
    if (watchedArr == null) {
      localStorage.setItem("watched", JSON.stringify([]));
    } else {
      watchedArr = JSON.parse(watchedArr);
    }
  }, []);
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 7월 30일

폼 미치따이

답글 달기