부모 컴포넌트로부터 props로 전달받은 값이 있는 태그의 자식 태그들은 자동으로 props.children
이 된다!
props.children
의 타입: ReactChild, ReactElement, ReactNode 등 다양하다. 예제에서는 JSX.Element
를 사용했다.
ReactElement 인터페이스를 상속받은 인터페이스로 ReactElement와 유사하다.
JSX.Element로 타입을 지정했을 때, children을 하나로 묶어주지 않으면 TS 에러가 발생한다.
interface IProps {
children: JSX.Element;
}
export default function Example(props: IProps) {
return (
<>
<header>Header</header>
<div>{props.children}</div>
<footer>Footer</footer>
</>
);
}
<> ~ </>
사용)import Example from "../../src/components/units/13-props-children-example";
export default function PropsChildrenPAge() {
return (
<>
<Example>
<>
{/* 자식 태그 */}
<input type="text" />
<button>버튼</button>
</>
</Example>
</>
);
}
UI가 모든 화면에 공통되어 고정시켜 놓는 부분을 레이아웃이라고 한다.
_app.tsx
파일에 설정을 입력하면 모든 파일에 적용이 된다.
header, nav 등을 미리 만들어놓은 컴포넌트를 Layout 만들고,
그 안에 변경되는 부분에 대한 컴포넌트를 넣는다.
props.children을 이용한다.
export default function Layout(props) {
return (
<>
<div> 헤더 </div>
<div> 배너 </div>
<div> 내비게이션 </div>
<div>{props.children}</div>
{/* props.children : _app.tsx의 Layout의 자식 */}
</>
);
}
모든 화면에 Layout의 내용이 함께 ㄴㅏ온다
🔹 Layout의 각 항목 컴포넌트화 하기
container / presenter 나눠도 된다.
import LayoutBanner from "./banner";
import LayoutFooter from "./footer";
import LayoutHeader from "./header";
import LayoutNavigation from "./navigation";
import styled from "@emotion/styled";
import { ReactNode } from "react";
const Body = styled.div`
height: 500px;
`;
interface ILayoutProps {
children: ReactNode;
}
export default function Layout(props: ILayoutProps) {
return (
<>
<LayoutHeader />
<LayoutBanner />
<LayoutNavigation />
<Body>{props.children}</Body>
{/* props.children : _app.tsx의 Layout의 자식 */}
<LayoutFooter />
</>
);
}
🔹 사이드바 만들기
const BodyWrapper = styled.div`
display: flex;
`;
const Body = styled.div`
height: 200px;
`;
const LayoutSidebar = styled.div`
width: 100px;
height: 200px;
background-color: orange;
`;
interface ILayoutProps {
children: ReactNode;
}
export default function Layout(props: ILayoutProps) {
return (
<>
<LayoutHeader />
<LayoutBanner />
<LayoutNavigation />
<BodyWrapper>
<LayoutSidebar>사이드바 영역</LayoutSidebar>
<Body>{props.children}</Body>
</BodyWrapper>
<LayoutFooter />
</>
);
}
🔹 페이지마다 노출 항목 지정하기
src/components/commons/layout/index.tsx
// HIDDEN_HEADERS: 숨길 페이지의 경로를 담은 배열
const HIDDEN_HEADERS = ["/12-05-modal-refactoring", "/12-01-modal-alert"];
export default function Layout(props: ILayoutProps) {
const router = useRouter();
const isHiddenHeader = HIDDEN_HEADERS.includes(router.asPath);
return (
<>
{!isHiddenHeader && <LayoutHeader />}
</>
);
}
router
pathname과 route는 실제 값이 들어가있지 않은 경로
asPath는 실제 값이 들어간 경로