-
[TS, React] styled-component에 ref 사용하기programing/Language 2020. 4. 17. 21:29
안녕하세요, Einere입니다.
(광고 차단 기능을 꺼주시면 감사하겠습니다.)
포트폴리오용 웹페이지를 구현하다가 React의 ref를 사용하려고 삽질한 후기를 공유하도록 하겠습니다.
원했던 그림
제가 하고자 했던 것은, 메뉴 버튼을 클릭하면 메뉴 컨테이너가 나타나는 기능이었습니다.
이를 위해 스타일을 클래스 네임으로 조작을 해야겠다고 생각했고, 클래스 네임을 조작하려면 컴포넌트에 대한 ref가 필요했습니다.
Prop에 ref 추가하기
위 요구사항을 위해 다음과 열심히 찾아서 다음과 같이 구현했습니다.
// NavBar.tsx import * as React from "react"; import {FunctionComponent, useCallback, useRef} from "react"; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {faBars} from '@fortawesome/free-solid-svg-icons' import {Logo} from '../Logo/Logo'; import {NavBarStyle} from "./NavBar.style"; import {NavBarMenu} from "./NavBarMenu"; export const NavBar: FunctionComponent = function () { const navBarMenuRef = useRef<HTMLDivElement>(null); const onClickHandle = useCallback(() => { console.log(navBarMenuRef.current); }, []); return ( <NavBarStyle> <Logo width={150}/> <FontAwesomeIcon icon={faBars} className="nav-bar-menu-icon" onClick={onClickHandle}/> <NavBarMenu ref={navBarMenuRef}/> </NavBarStyle> ); };
네비게이션 바 컴포넌트인
NavBar
에는 모바일 화면에서만 보이는 메뉴 아이콘(FontAwesomeIcon
)이 있습니다.이 컴포넌트가 클릭되었을 때, 네비게이션 바의 여러 메뉴를 담고 있는
NavBarMenu
의classList
를 조작하려고 합니다.// NavBarMenu.tsx import * as React from "react"; import {FunctionComponent, ForwardRefRenderFunction, Ref, ComponentPropsWithRef, useRef, forwardRef} from "react"; import {NavBarMenuStyle} from "./NavBarMenu.style"; import {NavBarMenuItem} from "./NavBarMenuItem"; interface Prop { ref: Ref<HTMLDivElement> } export const NavBarMenu:FunctionComponent<Prop> = function ({ref}) { const menu = ["about", "skill", "project"]; const MenuItems = menu.map((text, index) => <NavBarMenuItem text={text} key={index}/>); return ( <NavBarMenuStyle className="nav-bar-menu" ref={ref}> {MenuItems} </NavBarMenuStyle> ); };
NavBarMenu
컴포넌트는NavBarMenuStyle
이라는 div element를 reference합니다.// NavBarMenu.style.ts import styled from "styled-components"; export const NavBarMenuStyle = styled.div` display: flex; height: 100%; @media(max-width: 992px) { display: none; &.show { position: absolute; background-color: rgba(0, 0, 0, 0.5); top: 70px; left: 0; width: 100%; height: 0; transition: 0.5s ease; overflow: hidden; } } `;
NavBarStyle
은 위와 같습니다.그런데 콘솔에 다음과 같은 오류가 떴습니다..
음.. 함수형 컴포넌트는
ref
를 받을 수 없다고 하네요.또 열심히 찾아봅니다..
찾아본 결과,
ref
를 받기 위해서는React.forwardRef
함수를 사용해야 한다고 합니다.forwardRef 사용하기
forwardRef
를 사용한 코드는 다음과 같습니다.// NavBarMenu.tsx import * as React from "react"; import {forwardRef} from "react"; import {NavBarMenuStyle} from "./NavBarMenu.style"; import {NavBarMenuItem} from "./NavBarMenuItem"; export const NavBarMenu = forwardRef<HTMLDivElement>((props, ref)=> { const menu = ["about", "skill", "project"]; const MenuItems = menu.map((text, index) => <NavBarMenuItem text={text} key={index}/>); return ( <NavBarMenuStyle className="nav-bar-menu" ref={ref}> {MenuItems} </NavBarMenuStyle> ); });
forwardRef
의 제네릭에HTMLDivElement
를 주고, 함수의 인자로서props
와ref
를 받으면 됩니다. 그리고 인자로 받은ref
를NavBarMenuStyle
의ref
속성으로 넘겨주면 됩니다.아, 참고로
forwardRef<HTMLDivElement>()
의 반환값의 타입은React.ForwardRefExoticComponent<React.RefAttributes<HTMLDivElement>>
입니다. 참 기네요..테스트 하기
메뉴 버튼을 누르니 정상적으로 출력됩니다.
이거 해결할려고 몇시간동안 구글링했는지..ㅠㅠ
'programing > Language' 카테고리의 다른 글
[TS] d.ts 파일 작성시 이모저모 (0) 2020.05.17 [TS] 면접 대비용 TS 이모저모 (0) 2020.04.29 [TS] 깊은 복사(deep copy) 라이브러리 (0) 2020.03.30 [TS] Utility Types (0) 2020.03.18 [TS] TS with React - hook 사용하기 3 (0) 2020.02.23 댓글