React 컴포넌트를 조건부로 래핑하는 방법은 무엇입니까?


85

때때로로 렌더링해야 할 구성 요소가 <anchor>있고 다른 시간에는 <div>. prop내가 이것을 결정하는 읽기입니다 this.props.url.

존재하는 경우 <a href={this.props.url}>. 그렇지 않으면 그냥 <div/>.

가능한?

이것이 제가 지금하고있는 일이지만 단순화 할 수 있다고 생각합니다.

if (this.props.link) {
    return (
        <a href={this.props.link}>
            <i>
                {this.props.count}
            </i>
        </a>
    );
}

return (
    <i className={styles.Icon}>
        {this.props.count}
    </i>
);

최신 정보:

다음은 최종 잠금입니다. 팁 주셔서 감사합니다, @Sulthan !

import React, { Component, PropTypes } from 'react';
import classNames from 'classnames';

export default class CommentCount extends Component {

    static propTypes = {
        count: PropTypes.number.isRequired,
        link: PropTypes.string,
        className: PropTypes.string
    }

    render() {
        const styles = require('./CommentCount.css');
        const {link, className, count} = this.props;

        const iconClasses = classNames({
            [styles.Icon]: true,
            [className]: !link && className
        });

        const Icon = (
            <i className={iconClasses}>
                {count}
            </i>
        );

        if (link) {
            const baseClasses = classNames({
                [styles.Base]: true,
                [className]: className
            });

            return (
                <a href={link} className={baseClasses}>
                    {Icon}
                </a>
            );
        }

        return Icon;
    }
}

const baseClasses =해당 if (this.props.link)지점으로 이동할 수도 있습니다 . ES6 const {link, className} = this.props;를 사용 link하고 className있으므로 및 지역 변수 를 사용하여 약간 단순화 할 수도 있습니다 .
Sulthan

야, 나는 그것을 좋아한다. ES6에 대해 점점 더 많이 배우면 항상 가독성이 향상됩니다. 추가 팁에 감사드립니다!
Brandon Durham

1
"최종 잠금"이란 무엇입니까?
Chris Harrison

답변:


92

변수를 사용하십시오.

var component = (
    <i className={styles.Icon}>
       {this.props.count}
    </i>
);

if (this.props.link) {
    return (
        <a href={this.props.link} className={baseClasses}>
            {component}
        </a>
    );
}

return component;

또는 도우미 함수를 사용하여 콘텐츠를 렌더링 할 수 있습니다. JSX는 다른 것과 같은 코드입니다. 중복을 줄이려면 함수와 변수를 사용하십시오.


21

요소를 래핑하기위한 HOC (상위 구성 요소)를 만듭니다.

const WithLink = ({ link, className, children }) => (link ?
  <a href={link} className={className}>
    {children}
  </a>
  : children
);

return (
  <WithLink link={this.props.link} className={baseClasses}>
    <i className={styles.Icon}>
      {this.props.count}
    </i>
  </WithLink>
);

4
HOC 천천히 죽을 : P
제이미 Hutber

이 용어 HOC는 끔찍합니다. 중간에 놓인 기능 일뿐입니다. 나는이 갑자기 유행하는 이름 "HPC"를 정말로 대체한다. 수십 년 동안 오래된 개념 사이에 놓인 단순한 기능에 대해 너무 높은 순위입니다.
vsync

12

다음은 작업을 수행하는 데 사용 된 유용한 구성 요소의 예입니다 (누가 인증해야할지 확실하지 않음).

const ConditionalWrap = ({ condition, wrap, children }) => (
  condition ? wrap(children) : children
);

사용 사례 :

<ConditionalWrap condition={someCondition}
  wrap={children => (<a>{children}</a>)} // Can be anything
>
  This text is passed as the children arg to the wrap prop
</ConditionalWrap>

2
신용 가능성이 여기에 가야한다 : gist.github.com/kitze/23d82bb9eb0baabfd03a6a720b1d637f
로이 프린스

Kitze에서 봤어요. 그러나 나는 그가 다른 사람으로부터 아이디어를 얻었는지 확신하지 못했습니다
antony

나도 마찬가지다. 이것은 튀어 나온 첫 번째 결과 였고 나는 그것이 소스라고 생각했다-또는 적어도 그것에 가까운;).
Roy Prins

wrap좀 더 "반응"
정신

@vsync를 더 선언적으로 만들려면 어떻게해야합니까? 렌더 소품이 React의 정신 안에 있다고 생각 했나요?
antony

10

참조 변수를 사용할 수있는 또 다른 방법이 있습니다.

let Wrapper = React.Fragment //fallback in case you dont want to wrap your components

if(someCondition) {
    Wrapper = ParentComponent
}

return (
    <Wrapper parentProps={parentProps}>
        <Child></Child>
    </Wrapper>

)

당신은 전반을 요약 할 수 있습니다let Wrapper = someCondition ? ParentComponent : React.Fragment
mpoisot

이것은 멋지지만 때로는 코드를 선언적 으로 유지하고 싶을 때가 있습니다 . 즉, JSX
vsync

나는 얻을 오류를 React.Fragment can only have 'key' and 'children' 내가 좋아하는 "<래퍼>"몇 가지 소품을 통과하기 때문에 "클래스 이름" 등을
수직 동기화

@vsync propId = {someCondition? parentProps : undefined} ..
Avinash

1
알아요 :) 저는이 문제로 여기에 온 다른 사람들을위한 문서를 위해이 글을 작성했습니다. 따라서 Google은 해당 키워드에 대한 검색 결과에이 페이지를 캐시합니다
vsync

1

다음과 같은 util 함수를 사용할 수도 있습니다.

const wrapIf = (conditions, content, wrapper) => conditions
        ? React.cloneElement(wrapper, {}, content)
        : content;

0

여기에 설명 된대로 JSX if-else를 사용해야합니다 . 이와 같은 것이 작동합니다.

App = React.creatClass({
    render() {
        var myComponent;
        if(typeof(this.props.url) != 'undefined') {
            myComponent = <myLink url=this.props.url>;
        }
        else {
            myComponent = <myDiv>;
        }
        return (
            <div>
                {myComponent}
            </div>
        )
    }
});

-2

두 개의 구성 요소를 렌더링하는 기능 구성 요소, 하나는 래핑되고 다른 하나는 그렇지 않습니다.

방법 1 :

// The interesting part:
const WrapIf = ({ condition, With, children, ...rest }) => 
  condition 
    ? <With {...rest}>{children}</With> 
    : children

 
    
const Wrapper = ({children, ...rest}) => <h1 {...rest}>{children}</h1>


// demo app: with & without a wrapper
const App = () => [
  <WrapIf condition={true} With={Wrapper} style={{color:"red"}}>
    foo
  </WrapIf>
  ,
  <WrapIf condition={false} With={Wrapper}>
    bar
  </WrapIf>
]

ReactDOM.render(<App/>, document.body)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

다음과 같이 사용할 수도 있습니다.

<WrapIf condition={true} With={"h1"}>

방법 2 :

// The interesting part:
const Wrapper = ({ condition, children, ...props }) => condition 
  ? <h1 {...props}>{children}</h1>
  : <React.Fragment>{children}</React.Fragment>;   
    // stackoverflow prevents using <></>
  

// demo app: with & without a wrapper
const App = () => [
  <Wrapper condition={true} style={{color:"red"}}>
    foo
  </Wrapper>
  ,
  <Wrapper condition={false}>
    bar
  </Wrapper>
]

ReactDOM.render(<App/>, document.body)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.