TIL #4 - React로 Class 컴포넌트를 만든다구?

tami·2021년 8월 1일
7

TIL

목록 보기
4/9
post-thumbnail

React Class형 컴포넌트로 만들어야 한다는 미션을 받았다.

헉 React를 class로요..?

그래, 사실은 React 도 class형 컴포넌트로 가득찬시기가 있었다. 하지만 React v16.8부터 React Hook 을 지원해주면서 공식문서에서도 함수형 컴포넌트와 함께 사용할 것을 권장했기 때문에 처음 React를 배울 때 이후로 함수형으로 구현 하던 나였는데...

대외적으로는 "함수형이 권장이니까~"라고 말하지만 사실은 Class로 컴포넌트 구현하는 법을 잊어버린 나 자신을 감추며 간단히 React 기반의 상품 필터링을 구현했다.

Class 컴포넌트를 사용하며 느꼈던점 Hook의 부재로 인한 상태관리 삽질을 정리해보았다.

Class 컴포넌트 VS 함수형 컴포넌트 비교

Class형 컴포넌트

import React, { Component } from 'react'

export default class RecentList extends Component {
  render() {
    return (
      <div>
        
      </div>
    )
  }
}

함수형 컴포넌트

import React from 'react'

export default function RecentList() {
  return (
    <div>
      
    </div>
  )
}

차이점

class형

로직과 상태를 컴포넌트 내에서 구현 = stateful

  • state , setState를 이용한 상태관리
  • 내부 메서드 정의 가능
  • props 를 받아 this.props로 액세스 함
  • render() 함수가 있어야 하고 JSX를 반환해야함
  • component라이프사이클 메서드가 존재함 (componentDidMount,componentDidUpdate...)

함수형

로직과 상태를 props로 받아 뿌려줌 = stateless

  • React Hooks을 이용한 상태관리 가능 (useState)
    class에서의 라이프사이클메서드 역할을 Hook으로 사용 가능
  • useState: 상태 저장
  • useEffect(callback,[]): 수명주기 동작 조정

useEffect

  • 빈배열을 두번째 인수로 전달하면 초기 렌더링 후에만 useEffect에서 callback을 트리거하여 componenetDidMount수명주기동작을 복제한다.
  • event를 넣으면 구성요소가 마운트 해제될 때 실행될 함수를 반환하여 리스너 구독을 취소할며 comoponentWillUnMount 기능 수행

잘못된 설계와 그로 인해 배운점


gif용량변화로 인해 영상이 깨지는점..양해바랍니다....

1️⃣ 초기 설계

export default class RecentList extends Component {
  state = {
    recentFiltered: [],
    brandList: [],
    isUnlike: '',
  };
//중략

상태

state설명
recentProductslocalStorage에서 가져온 최근 상품항목
recentFiltered필터링 될 때마다의 상품리스트
brandList최근 상품 항목들의 브랜드 종류 리스트

각각의 필터를 클릭했을 시 클릭이벤트가 this.setState해 recentFiltered를 업데이트 하는 방식

메서드

setLowPriceOrder = () => {
    const { recentFiltered } = this.state;
    const lowOrderedList = recentFiltered.sort((a, b) => {});
    this.setState({ recentFiltered: lowOrderedList });
  };

setHighPriceOrder = () => {
    const { recentFiltered } = this.state;

    const highOrderedList = recentFiltered.sort((a, b) => {});
    this.setState({ recentFiltered: highOrderedList });
  };

setRecentViewOrder = () => {
    this.setState({ recentFiltered: getStore('recentViewed')});
  };

2️⃣ 문제점

중복된 state는 잘못 설계되었다.

데이터 정규화가 안 된 상태
state는 서로의 state를 가지고 있으면 안되고 함수형 체이닝을 통해 재연산을 해야지 중복적으로 가지고 있으면 상태변경에 대한 추적이 어렵다.

너무 잦은 state 변경

함수형 체이닝이 아닌 함수 자체에서 각각 setState를 통해 상태를 변경하기 때문에 유지,보수와 상태변경 추적이 매.우 어렵다
실제로) 잦은 state변경으로 인해 변경하지도 않은 원본상품리스트가 변경되는 sideEffect 발생

3️⃣ 개선 방향

state 변경

중복된 state인 recentProducts를 제거하여 각 함수에서는 props로 해당 값을 받아서 사용하게 변경해야 한다.

함수의 역할 제한

현재 함수는 직접 state를 변경하지만 함수는 props(localStorage에서 가져온 최신상품리스트)를 이용해 필터링한 상품리스트만 return한다.

<개선 전>

render() {
    const { recentFiltered } = this.state;
    return (
      {recentFiltered.map((product) => {
            const { id } = product;

<개선 후>

render() {
  const recentProducts = localSotrage.getItem(~
  const viewdProducts = setHighPriceOrder(recentProducts)
    return (
      {viewdProducts.map((product) => {
            const { id } = product;

즉 기존에는 다 필터링된 상품리스트를 this.state에서 가져와 렌더링했지만
localStorage에서 가져온 데이터를 메서드로 필터링한 후 바로 렌더링 하는 것이다.
즉 필터링한 리스트를 상태로 가지고 있을 필요없이 바로 렌더링 해주면 되는 방향으로 변경하는 것이다.

프로젝트 설계 시 고려할 점

이로 인해 고통받으며 설계 시 고려해야 할 점을 정리해보았는데,

state 변경은 최소화 해야 한다

특히 this.state는 전역변수와 같은 존재인데, 모든 함수에서 이 state의 상태를 갱신하고 조작했다.
상태는 사용자의 입력에 따라 반응해야 하는데, Component 렌더링에 매우 의존적이게 되었고 이로 인해 추적 또한 어려워졌다.

React를 사용할 때에는 component재랜더링을 우선적으로 고려해야 한다.

2가지 상태(원본상품리스트, 필터링상품리스트)를 다 가지고 있었던 이유는 localSotrage에 계속적으로 접근하면 안좋다고 막연하게 생각해서였는데,

일단 localStorage는 성능상에 그렇게 큰 영향을 끼치지 않고 만약 성능상의 문제라면 component가 재렌더링에 더 초점을 둬야 한다는 결론은 얻었다.

localStorage에서 가져올 데이터는 사실상 실무에서는 서버에서 API 호출이다가져오는 것인데 실시간으로 최신상품을 보여줘야 하기 때문에 성능저하를 감수하더라도 매번 데이터를 가져오는 것이 필요하다는 것이 결론이다.

또 localStorage(=미래API요청)은 한곳에서 호출되면 네트워크 이슈 발생 시 추적이 편리하기 때문에 render에서 한번만 불러오는 것이 디버깅하기 쉽다.

✨ state는 사용자 UI 상태를 관리하는 것이고, component가 재렌더링될때마다 날라가는건 이런 이유때문이 아닐까.. 라고 똑똑한 동료들과 함께 결론을 맺었다.

상태관리 다음엔 제대로 해줄게.


참고
React 함수의 Class Component

위코드 X 원티드 프리온보딩 코스

현재 위코드와 프리온보딩 코스에 참여하고 있는데,
평소에 지나쳤던 기본적인 부분들을 다시금 체크하고,
또 그냥 뚝딱 만드는것에만 집중하지 않고 왜왜왜 했는지 조원분들이랑 공유하면서 많이 공부하고 있다.
모두 너무 감사합니다~~

profile
자스베이더 Tami의 TILAND에 오신걸 환영합니다🗡

0개의 댓글