프로젝트 노트 📝

[React][SD] 스타일이 다른 header를 하나의 컴포넌트로 해결하기

수끼옹 2022. 12. 27. 14:36

(오늘의 포스트는 그냥 제가 기억하기 위해 쓴 포스트이니 ... 허접한 글일 수 있겠네요)

 

안녕하세욥? 저는 지금 열심히 studio dragon사의 웹사이트를 리팩토링 하는 중이랍니다 ㅎㅎ 요즘은 옛날보다 작업속도가 조금 빨라진 것 같아서 나름 뿌듯하지만 현직 개발자에 비하면 애송이 baby 그 자체. 더욱 스스로를 채찍질 해야겠어요

-

어쨌든, 본론으로 돌아와서! 페이지 작업을 하다보니 이 웹사이트는 header가 두 가지 스타일이더라구요

Black 버전
White 버전

하나는 뒤의 background가 없이 요소들의 색이 black이고 구분선이 있는 header이고, 다른 하나는 뒤의 background 이미지가 있어서 white로 색을 통일하고 구분선이 없어진 header입니다.

 

저는 그냥 단순하게 생각을 해서 header 컴포넌트를 black, white 두 종류로 만들고, Route로 각각 공통 레이아웃으로 만들어 header의 디자인에 따라 페이지들을 넣어주려고 했습니다.

 

그런데 저의 멘토가 한마디 해주더군요 header 컴포넌트를 두개로 만들지 않고도 하나의 header 컴포넌트로도 두 가지 버전의 header를 만드는 게 가능하다구요 !!

 

요약하자면

- Header.jsx

- HeaderW.jsx

- BlackLayout.jsx

- WhiteLayout.jsx

4개의 파일들을

 

- Header.jsx

- BlackLayout.jsx

- WhiteLayout.jsx

이처럼 3개의 파일로 줄일 수 있었습니다.

 

그렇담 설명 들어갑니다 🕶 ~ ~ ~


1. 먼저 black, white 버전의 header 레이아웃을 작성합니다.

// BlackLayout.jsx

import { Outlet } from "react-router";
import Header from "../components/Header";

const BlackLayout = () => {
  return (
    <>
      <Header id="black" />
      <Outlet />
    </>
  );
};

export default BlackLayout;
//WhiteLayout.jsx

import { Outlet } from "react-router-dom";
import Header from "../components/Header";

const WhiteLayout = () => {
  return (
    <>
      <Header id="white" />
      <Outlet />
    </>
  );
};

export default WhiteLayout;

App.js 파일에서 부모 레이아웃으로 사용할 것이기 때문에 Outlet을 이용해줍니다. 여기서 중요한 것은 각각의 Header 컴포넌트에 id값을 넘겨줘야 한다는 것입니다. id값을 이용해서 id별로 각각 다른 스타일을 적용해줄 수 있기 때문입니다.

 

2. 이제 Header 컴포넌트를 제작합니다.

먼저 스타일 컴포넌트를 제외한 코드를 보시겠습니다?

// Header.jsx

import styled from "styled-components";
import { langOnState } from "../store/LangAtom";
import { useRecoilState } from "recoil";

const Header = ({ id }) => {
  const [lang, setLang] = useRecoilState(langOnState);

  return (
    <Wrapper id={id}>
      <HeaderWrap>
        <Menu id={id} />
        <Logo id={id} />
        <Lang>
          <List
            id={lang === "kor" ? `selected_${id}` : undefined}
            onClick={() => setLang("kor")}
          >
            KOR
          </List>
          <List id="bar">|</List>
          <List
            id={lang === "eng" ? `selected_${id}` : undefined}
            onClick={() => setLang("eng")}
          >
            ENG
          </List>
        </Lang>
      </HeaderWrap>
    </Wrapper>
  );
};

export default Header;

아까 위에서 만든 layout에서 id값을 넘겨줬었죠? 그래서 id값을 파라미터로 쓴 것입니다! 여기서 주의할 점은 { id }로 쓰지 않으면 props.id로 써야 돼서 {}안에 id를 넣어줘야 쓰기가 쉽다는 점입니다?

 

코드를 보면, 스타일이 달라져야 하는 부분에 id를 넣어줬습니다. 이제 저 id값을 이용해서 스타일 컴포넌트를 만들어주면 끝입니다 ㅎㅎ

 

스타일 컴포넌트를 보시겠습니다.

// Hedaer.jsx의 스타일 컴포넌트
const Wrapper = styled.div`
  width: 100%;
  &#white {
    position: absolute;
  }
  &#black {
    border-bottom: 1px solid #7c7c7c;
  }
`;
const Menu = styled.div`
  width: 35px;
  height: 35px;
  background-size: contain;
  cursor: pointer;
  &#white {
    background: url("/img/sub_ham_w.png") no-repeat center center;
  }
  &#black {
    background: url("/img/sub_ham.png") no-repeat center center;
  }
`;
const Logo = styled.div`
  width: 128px;
  height: 53px;
  background-size: contain;
  &#white {
    background: url("/img/logo_w.png") no-repeat center center;
  }
  &#black {
    background: url("/img/logo.png") no-repeat center center;
  }
`;
const List = styled.li`
  cursor: pointer;
  color: #ccc;
  &:hover {
    text-decoration: underline;
  }
  &#selected_white {
    color: #fff;
    font-weight: 500;
  }
  &#selected_black {
    color: #000;
    font-weight: 500;
  }
  &#bar {
    cursor: default;
    text-decoration: none;
    font-size: 14px;
  }
`;

이런식으로 black과 white의 스타일이 구분되어 집니다.

 

3. 마지막으로 Route 설정을 해준다.

// App.js

<Routes>
    <Route path="/" element={<BlackLayout />}>
        <Route path="about" element={<About />} />
        <Route path="contact" element={<Contact />} />
    </Route>
    <Route path="/" element={<WhiteLayout />}>
        <Route path="contents" element={<Contents />} />
    </Route>
</Routes>

Layout별로 페이지를 자식으로 넣어주면 끝입니다 완성 ~

 


 

뭔가.. 내용은 제일 없는 것 같은데 코드 땜에 글이 길어졌군여... 그럼 다음 포스팅까지 안녕히 ~!