선택한 영역 강조하고, 특정 컴포넌트 불러오기

라용·2022년 11월 15일
0

위코드 - 스터디로그

목록 보기
99/100

위코드 기업협업에 참여하며 정리한 내용입니다.

특정 영역을 클릭하면 해당 영역이 포커스되면서 강조 표시가 유지되고, 그 영역에 맞는 컴포넌트를 불러와서 우측에 띄워주는 기능을 아래처럼 구현했다. View 컴포펀트 안에 ViewNav 는 아래와 같은 형태를 가지는데, 태일윈드를 사용했으므로 삼항연산자로 id 값을 비교해 클래스를 추가하는 방식을 적용했다. 하지만 간혹 적용되지 않는 스타일은, 클래스 명 변경으로 반영이 되지 않아서 별도 인라인 스타일을 사용했다.(이렇게 변화가 적용되지 않는 속성이 몇몇 있는 것 같음) focusId 를 결정하는 sectionClick 함수는 View 컴포넌트에서 전달하는 데 해당 함수는 클릭한 타겟의 id 를 저장하므로 ViewNav 의 div 가 가진 id 값을 가져오게 된다.

// ViewNav.tsx

interface NavDataProps { // 아래 컴포넌트가 인자로 전달받은 데이터의 타입
  data?: NavData; // NavData 는 다른 곳에서 정의한 데이터 타입을 불러와 사용한 것
  focusId: string;
  sectionClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
}

const ViewNav = ({ data, focusId, sectionClick }: NavDataProps) => {

  if (!data) return <>loading...</>; // 데이터가 없을 경우 로딩

  // 전달받은 데이터를 구조분해할당  
  const { box_image_url, menu_list, bg_color, section_title_color } = data;

  return (
    <div
      id="nav" // 이 id 가 아래 onClick 함수로 전달되어서 focusId 로 세팅되는 것
      className={`flex justify-between items-center ...
      // 삼항연산자로 전달받은 id 를 비교해 
      ${focusId === "nav" ? "border-2 border-main_purple scale-[1.01]" : ""}`} 
      style={{ backgroundColor: `${bg_color}` }} // 클래스로 적용 안될 경우 인라인 스타일 사용
      onClick={sectionClick}
    >
    ...  
 
    </div>
  );
};

export default ViewNav;

// View.tsx

  const sectionClick = (e: MouseEvent<HTMLButtonElement>) => {
    const target = e.currentTarget.id; // 클릭한 요소의 id 를 담아
    return setFocusId(target); // focusId 로 세팅
  };

이렇게 저장한 Id 값인 focusId 를 사용해 특정 컴포넌트를 불러오는데, 일단 focusId 를 해당 하위 컴포넌트에 프롭으로 전달하고 그 id 와 컴포넌트를 매칭한 배열을 만들어 find 메서드로 해당 요소의 id 와 focusId 가 같은 요소를 추출합니다. 그리고 그 컴포넌트를 화면에 출력합니다.

const EditPanel = ({ focusId, onApplyClickEvent }: ClickEventProps) => {
  ...
    
  // id 별로 보여줄 컴포넌트 정리
  const EDIT_PANEL = [
    { id: "nav", panels: EditPanelNav },
    { id: "main", panels: EditPanelMain },
    { id: "imageSlide", panels: EditPanelImageSlider },
    { id: "leftTextRightImage", panels: EditPanelLeftRightImage },
    { id: "textCard", panels: EditPanelTextCard },
    { id: "introText", panels: EditPanelIntroText },
    {
      id: "leftTextRightMultiImages",
      panels: EditPanelLeftTextRightMultiImages,
    },
    { id: "textSlide", panels: EditPanelTextSlide },
    { id: "footer", panels: EditPanelFooter },
  ];
  
  // id 를 비교해서 보여줄 컴포넌트 선택    
  const focusEditPanel: any = EDIT_PANEL.find((item) => item.id === focusId);

  return (
    <div className="ml-5 ">
      ...

      <div className="sticky top-8">
        <div className="w-[500px] p-10 text-sm bg-white shadow-md ">

          // foucsId 여부에 따라 해당 요소를 보여주거나 디폴트 화면을 보여줌
          {focusId.length !== 0 ? (
            <focusEditPanel.panels
              editInfo={editInfo}
              updateEditInfo={updateEditInfo}
            />
          ) : (
            <EditPanelDefault />
          )}
        </div>

        ...
      </div>
    </div>
  );
};

export default EditPanel;
profile
Today I Learned

0개의 댓글