til

리액트 숙련 3일 차 @개인과제 60%

fpzmfks 2024. 8. 20. 20:13

오늘 바로 개인과제를 60% 완성했다. 이번 과제는 브런치를 따로 파서 같은 프로젝트를 2가지 버전으로 작성해야해서 그렇지, 오늘 2가지 버전 중 1가지 버전을 완성했으니 거의 완성했다고 보아도 될 것이다. 

 

내가 먼저 완성한 버전은 props-drilling이 발생하는 버전이다. props-drilling이란 부모요소에서 선언된 데이터 등이 자식요소에서 사용되기 위해 props로 전달되는 과정이 불필요하고 번거로운 것을 나타낸다. 예를 들어 1-2-3-4-5의 순으로 부모요소에서 자식요소가 있을 때 1에 있는 값을 5로 전달하려면 중간의 2-3-4 또한 자신에게 불필요한 값을 부모로부터 전달받아야 한다. 이러한 불편한 구조를 개선하기 위해 useContext를 사용하는 것이 남은 과제이다. 

 

오늘 한 과제에서 props-drilling으로 인해 인상적으로 어려움을 겪은 것은 없다. props-drilling의 불편함은 입문주차 과제에서도 확실히 느꼈기 때문에 컴포넌트 구조를 잘 활용하려면 props로 값을 전달하는 건 불편하다는 것만 짚고 넘어가면 될 듯하다. 

 

약간 난관을 겪은 것은 어제 부딪친 if문과 컴포넌트를 조합하는 문제와 querystring으로 spa를 구성하는 것이었다. 이러한 문제들은 해결하긴 했는데... 더 좋은 해결 방법이 있을 것 같아서 아직까지 고민이 된다. 

 

먼저 if문과 컴포넌트를 조합하는 문제이다.

 

이 문제의 경우, 값이 존재할 때와 존재하지 않을 때에 따라 다른 컴포넌트를 출력하는 것이 목적이다.

 

이렇게 출력해야하는 컴포넌트가 6개이기 때문에, 처음에는 map을 돌려서 컴포넌트를 출력하려고 했다. 하지만 map을 돌리는 배열의 길이가 적으면 '값이 없는 경우의 컴포넌트'가 아니라 '컴포넌트가 출력되지 않는 문제'가 생겼다. arr=[null, null, null, null, null, null]을 만들어서 어떻게 잘 활용해보려고도 해보았는데, 이러한 방식은 다른 모든 대책보다도 더 복잡하고 번거로운 코드가 완성될 것 같아서 이 안은 폐기했다. 

 

다음 대책은 하위 컴포넌트에서 상태값을 물려받아 자체적으로 해결을 보는 것이었다. 하지만 이러한 방식은 하나의 컴포넌트의 길이가 너무 길어지는 문제가 있기 때문에 기각했다. 

 

때문에 이게 될까? 생각해서 미뤄두고 있던 대안으로 해당 문제를 해결했다. 바로 아래 코드이다. 

<AddDiv>
  <AddForm data={poke[0]} poke={poke} setPoke={setPoke} />
  <AddForm data={poke[1]} poke={poke} setPoke={setPoke} />
  <AddForm data={poke[2]} poke={poke} setPoke={setPoke} />
  <AddForm data={poke[3]} poke={poke} setPoke={setPoke} />
  <AddForm data={poke[4]} poke={poke} setPoke={setPoke} />
  <AddForm data={poke[5]} poke={poke} setPoke={setPoke} />
</AddDiv>
const AddForm = ({ data, poke, setPoke }) => {
  if (data) {
    return <AddCard data={data} poke={poke} setPoke={setPoke} />;
  } else {
    return (
      <BlankImageDiv>
        <BlankImg className="addImage" src="../../public/pokeball-icon.png" />
      </BlankImageDiv>
    );
  }
};

 

컴포넌트 6개에 각기 다른 상태값을 물려줘서 해당 값이 존재할 때와 존재하지 않을 때 각기 다른 컴포넌트가 출력되도록 했다. 현재로썬 이게 최선의 방법인데... context api를 쓸 때는 이 문제를 또 어떻게 해결할 수 있을지 아직 감이 안 잡히는 게 문제이다. 그때야말로 arr=[null, null, null, null, null, null]을 사용해야하는걸까?

 


다음 난관은 querystring으로 spa를 구성하는 것이다. 얼핏 보기에 썩 어렵지 않은 것 같아서 미뤄둔 것이었는데, 임의의 카드를 클릭하면 해당 카드의 상세페이지로 querystring을 타고 넘어가는 것이다. 그런데 생각보다 해맸던 것이, querystring을 위한 ?id= 의 형식을 어디에 두어야 할지, 중복해야할지 같은 문제가 있었다. 결론적으로는 Router.jsx파일에는 ?id=를 넣지 않고, 상세페이지로 넘어갈 때 ?id= 를 넣어야한다. 간단하고 대강 납득할 수 있는 결론이지만, 이 결론을 얻기 위해 시행착오를 해야했기 때문에 인상적인 기억으로 남았다. 

 

다만 찜찜한 게 하나 남아있는데 쿼리스트링으로 넘어온 id 번호로 상세페이지의 데이터를 채워넣으려니까 id 번호만 딱 깔금하게 추출할 수 있는 적당한 방법을 찾을 수 없었던 것이다. 

const location = useLocation();
  const queryString = location.search.slice(4);

때문에 쿼리스트링으로 넘어온 id 정보를 추출하기 위해 slice를 사용하여 ?=id  8 에서 ?=id를 떼어내어 8만 가져가는 방식을 취했다. 썩 깔끔한 방식은 아닌지라 쿼리스트링을 더 잘 활용할 수 있는 방법이 있는지 찾아보아야 할 것 같다.