import'./AppHomeLink.scss'import React from'react'import { string } from'prop-types'constAppHomeLink= ({ children, external,...domProps }) => {return ( <h1className="appHeader__brand"> <a// 기본값이 아닌 사용자가 입력한 나머지 속성이 포함되도록 한다. {...domProps}className="appHeader__homeLink"// external 속성에 true/false를 사용해서 두 개의 속성을 모두 설정하거나 제거 하도록 할 수 있다.target={external ?'_blank':null}rel={external ?'noopener noreferrer':null} > {/* 기본 값이 필요한 속성은 아래와 같이 기본 값을 할 수 있다. */} {children ?? <spanclassName="a11yHidden">홈링크</span>} </a> </h1> )}// href이 반드시 전달 될 수 있도록 propTypes를 설정한다.AppHomeLink.propTypes = { href:string.isRequired,}exportdefault AppHomeLink
constAppHomeLink= ({// wrapperProps을 구조 분해 할당 하여 사용한다. // 이때 AppHomeLink가 전달받은 className과 // wrapperProps가 전달받은 wrapperClassName의 속성이름이 같으면 안되서 다르게 설정했다. // wrapperProps: { wrapperClassName, ...restWrapperProps }, wrapperProps: { as: WrapperComponent className: WrapperClassName,...restWrapperprops }, children, external, className,...domProps}) => {// classNames를 사용해서 클래스 이름을 중첩되게 한다. constcombineWrapperClassNames=classNames('appHeader__brand', WrapperClassName ??'' )return (// 전개 연산자를 사용해서 래퍼 요소에 속성이 적용될 수 있도록 한다. <WrapperComponent {...restWrapperprops} className={combineWrapperClassNames}> </WrapperComponent> ) }
4. 요소 별칭 등록
as 속성을 사용해서 별칭을 등록할 수 있다.
4.1 부모 컴포넌트
<AppHomeLinkwrapperProps={{// as 속성을 사용해서 변경할 태그 네임을 문자열로 전달한다. as:'h2', className:'wrapper', title:'래퍼', }}>
4.2 자식 컴포넌트
constAppHomeLink= ({// 전달 받은 as 속성에 별칭을 등록하고 wrapperProps: { as: WrapperComponent, wrapperClassName,...restWrapperProps }}) => {constwrapperClassNames=classNames('appHeader__brand', wrapperClassName ??'' )return (// h1 요소의 이름으로 설정하면 h1 → h2로 변경된다. <WrapperComponent {...restWrapperProps} className={wrapperClassNames}> </WrapperComponent> )}// as의 기본 값을 h1으로 설정 AppHomeLink.propTypes = { wrapperProps: { as:'h1' }}
5. props 전개
컴포넌트로 전달된 props 객체를 전개(spread) 하여 컴포넌트의 내부의 구조(Markup)에 모두 추가 설정할 수 있다.
<Component {...props} />
다만, props 객체의 속성을 전개하였을 때 사용된 external과 같은 비 표준 속성은 오류를 발생시킨다.
Warning: Received `true` for a non-boolean attribute `external`.
If you want to write it ti the DOM, pass a string instead: external="true" or external={value.toString()}.
오류 메시지에서 해결책을 안내하고 있지만, 안내 방법대로 해도 해결이 안되는 경우가 있다. 이런 경우 컴포넌트로 전달된 props에서 비 표준 속성을 걸러내어 문제를 해결 할 수 있다. (<a> DOM Node에 설정되는 속성이므로 aNodeProps라는 이름을 사용했습니다)
import React from'react'import classNames from'classnames'constAppButton= ({ children, handleNav, className, label,...restProps}) => {constbuttonClassNames=classNames('resetButton', className ??'')return ( <button {...restProps}onClick={handleNav}className={buttonClassNames}// type 버튼의 경우는 기본값을 사용할 필요없다. 왜냐하면 해당 컴포넌트는 Button으로만 사용할 것이기 때문에 변하지 않는다.type="button"// title과 aria-label 값이 동일하니 label로 한번에 설정할 수 있다.title={label ??null}aria-label={label ??null} > {children ?? <spanclassName="ir"></span>} </button> )}exportdefault AppButton