프리온보딩 코스 2주차 과제 리팩토링

YUZAMIN
Hello, World! I'm YUZAMIN, a diligently endeavoring frontend developer 🐤💦
프리온보딩 코스 2주차 과제 리팩토링

2주차 미스터카멜 과제

1st Problem💥

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
// src/Pages/List/List.js

handleClick(product) {
    let data = []
    data = GetDataFromLocalStorage(WATCHED) || []
    if (data) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].index === product.index) {
          if (data[i].interest === false) {
            alert(ALERT_NOT_INTERESTING_PRODUCT)
            return
          } else {
            data[i].date = product.date
            MoveAfterVisit(data, `/product/${product.index}`, this.props)
            return
          }
        }
      }
      data.push(product)
      MoveAfterVisit(data, `/product/${product.index}`, this.props)
      return
    }
    data.push(product)
    MoveAfterVisit(data, `/product/${product.index}`, this.props)
  }
  • 하나의 함수가 수행하는 기능이 너무 많음 → 한 눈에 어떤 기능을 수행하는지 알기 어려움, 이해하는 데 시간 소요

  • LocalStorage에서 상품 조회 기록을 불러와서 변수에 할당할 때 Util function을 이용하는데, 매번 새로 변수를 만들고, 초기화하는 과정에서 불필요한 코드가 발생

Solution✅

1
2
3
4
5
6
// src/utils/GetDataFromLocalStorage.js

const GetDataFromLocalStorage = (key) => {
  return JSON.parse(localStorage.getItem(key)) || []
}
export default GetDataFromLocalStorage
  • 만약 해당 key를 갖는 데이터가 LocalStorage에 저장되어 있지 않을 경우 Util 함수 내부에서 자체적으로 빈 배열을 변수에 할당하도록 함 → 해당 함수를 사용하는 곳에서 undefined가 반환될 것을 대비하여 굳이 추가로 빈 배열을 할당할 준비를 해둘 필요가 없어짐
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
31
32
33
34
35
36
37
  isWatched(product) {
    const watchedProduct =
      this.state.histories?.find(
        (history) => history.index === product.index
      ) || null
    return watchedProduct
  }

  deleteHistory(product) {
    const newWatchedHistory = this.state.histories.filter((history) => {
      return history !== product
    })
    console.log(newWatchedHistory)
    return newWatchedHistory
  }

  MoveAfterAddToWatched(history, product, idx) {
    history.push(product)
    MoveAfterPush(history, `/product/${idx}`, this.props)
  }

  handleClick(product) {
    const watchedProduct = this.isWatched(product)

    if (!watchedProduct) {
      this.MoveAfterAddToWatched(this.state.histories, product, product.index)
      return
    }
    if (watchedProduct?.interest) {
      const newWatchedHistory = this.deleteHistory(watchedProduct)
      this.MoveAfterAddToWatched(newWatchedHistory, product, product.index)
      return
    } else {
      alert(ALERT_NOT_INTERESTING_PRODUCT)
      return
    }
  }
  • 기능 별로 함수를 만들어서 하나의 함수가 하나의 일만을 할 수 있도록 함

  • ‘해당 값이 존재하는 경우(undefined가 아닌 경우)’를 표현하기 위해 물음표 사용 ex) watchedProduct?.interest

2nd Problem💥

1
2
3
4
5
6
7
      const newProduct = this.state.wholeProducts[randomNum]
      const date = new Date()
      const tempObj = { index: randomNum, date: date, interest: true }
      const product = Object.assign(tempObj, newProduct)
      data.push(product)
      MoveAfterVisit(data, `${PRODUCT_URL}/${randomNum}`, this.props)
      return
  • randomNum을 index로 가지는 상품의 조회 내역 존재하지 않는 경우, 해당 index의 상품 정보를 wholeProducts data로부터 검색 후 가져와서 parsing(index, date, interest 정보 추가), LocalStorage에 parsing된 상품 정보 추가 후 해당 상품 상세 페이지로 방문하는 로직

  • 해당 부분 또한 어떤 함수 안에 담긴 로직인데, 단일 책임 원칙을 지키기 위해 따로 함수를 만들어서 분리하는 것이 좋음

Solution✅

  • 함수 정의
1
2
3
4
5
6
7
8
  saveNewRandomProduct(data, randomNum) {
    const newProduct = this.state.wholeProducts[randomNum]
    const date = new Date()
    const tempObj = { index: randomNum, date: date, interest: true }
    const product = Object.assign(tempObj, newProduct)
    data.push(product)
    MoveAfterPush(data, `${PRODUCT_URL}/${randomNum}`, this.props)
  }
  • 사용
1
2
      this.saveNewRandomProduct(data, randomNum)
      return

repo link