[react] 반복문의 useState

Hyunwoo Jin·2022년 9월 2일
0

map 함수로 여행지 항목을 담은 detailList 가 있다.
그리고 스켈레톤 ui를 적용시키기 위해 렌더링 상태를 loading state를 생성하여 관리하려했다. 하지만 이렇게 되면 개별적인 렌더링 상태를 구분할 수 없다.

const [loading, setLoading] = useState(true);
const detailList = Data.region[value].detail.map(function (detail, index) {
    return (
      <Link
        to={`${detail.id}`}
        className="card"
        key={detail.id}
        state={3}
        onClick={() => {
          window.scrollTo({
            top: 0,
          });
          dispatch(changeDetail(Data.region[value].detail[index]));
        }}
      >
        {loading ? <SkeletonPoint /> : ""}
        <img src={detail.image} alt="여행지이미지" />
        <div className="card-txt">
          <h2 className="card-title">{detail.name}</h2>
          <p className="card-desc">{detail.description}</p>
        </div>
      </Link>
    );
  });

결국 <Link> 부분을 PointBox.js 라는 하나의 컴포넌트로 만들었다.

// PointBox.js
<PointBoxEl>
      <Link
        to={`${detail.id}`}
        className="card"
        key={detail.id}
        state={3}
        onClick={() => {
          window.scrollTo({
            top: 0,
          });
          dispatch(changeDetail(Data.region[value].detail[index]));
        }}
      >
        <img
          src={detail.image}
          alt="여행지이미지"
          onLoad={() => setLoading(false)}
        />
        <div className="card-txt">
          <h2 className="card-title">{detail.name}</h2>
          <p className="card-desc">{detail.description}</p>
        </div>
      </Link>
</PointBoxEl>

멍청한 나자신, 보잘 것 없는 버튼 하나를 컴포넌트로 굳이 만들어 컴포넌트마다 useState useDispatch redux 등 import 를 계속할 것인데..
이게 코드 성능 상 좋을 리가 없잖아.......
렌더링되는 시간동안 사용자에게 양해를 구하는 스켈레톤 ui를 제작 중인데
스켈레톤 ui 덕에 렌더링이 더 늦어지면 주객전도가 아닌가?
배보다 배꼽이 더 큰 상황이다.
다시 컴포넌트화했던 여행지 버튼을 다시 돌려놓았다.
그리고 새로운 방법을 떠올렸다.


const detailList = Data.region[value].detail.map(function (detail, index) {
	const [loading, setLoading] = useState(true);
    return (
      <Link
        to={`${detail.id}`}
        className="card"
        key={detail.id}
        state={3}
        onClick={() => {
          window.scrollTo({
            top: 0,
          });
          dispatch(changeDetail(Data.region[value].detail[index]));
        }}
      >
        {loading ? <SkeletonPoint /> : ""}
        <img src={detail.image} alt="여행지이미지" />
        <div className="card-txt">
          <h2 className="card-title">{detail.name}</h2>
          <p className="card-desc">{detail.description}</p>
        </div>
      </Link>
    );
  });

arrow function 을 변경하고 맵함수 내에서 항목마다 개별적으로 loading state를 만들어 렌더링 상태를 확인하려고 했다. 하지만?

아 글쎄 콜백 내에서 useState 호출 불가란다.
왜그러냐믄 React hooks 은 함수 구성요소나 react hook 함수에서만 호출해야 된단다.
하기사 됐어도 '아 ㅋㅋ 이게 되네?' 했을 터,

방안

여러가지 고민 후 컴포넌트를 분리하되 import를 최소화하도록 분리했다.

import React, { useState } from "react";
import styled from "styled-components";
import SkeletonPoint from "./SkeletonPoint";
const PointBox = ({ detail }) => {
  const [loading, setLoading] = useState(true);
  return (
    <PointBoxEl>
      {loading ? <SkeletonPoint /> : ""}
      <img
        src={detail.image}
        alt="여행지이미지"
        onLoad={() => setLoading(false)}
      />
      <div className="card-txt">
        <h2 className="card-title">{detail.name}</h2>
        <p className="card-desc">{detail.description}</p>
      </div>
    </PointBoxEl>
  );
};

구현을 했지만 결국 추후 API 통신으로 데이터를 전달받을 경우
컴포넌트를 굳이 분리할 필요도 없고 그로 인한
불필요한 코드가 오히려 많아질 가능성이 높아 보인다.

결론

원래대로 돌아간다.
스켈레톤 UI (임시) 는 보류
백이 생기고 API 통신이 이루어질 시 임시로 저질러놓은 코드를 다시 보수해야 될 것이다.

profile
꾸준함과 전문성

0개의 댓글