我如何有条件地包装React组件?

时间:2015-11-14 16:48:49

标签: javascript reactjs

我有一个组件有时需要渲染为锚点,其他时候需要渲染为简单的div。我prop触发确定哪个是this.props.url道具。如果它存在,我需要使用href={this.props.url}渲染包裹在锚点中的组件。否则它只会呈现为<div/>

可能的?

这就是我现在正在做的事情,但感觉它可以简化:

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

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

UPDATE:

这是最后的锁定。感谢您的提示,@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;
    }
}

9 个答案:

答案 0 :(得分:62)

只需使用变量。

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就像其他任何代码一样。如果要减少重复,请使用函数和变量。

答案 1 :(得分:9)

创建一个HOC(高阶组件)来包装元素:

passport.use(new twitchStrategy({
    clientID: config.twitchID,
    clientSecret: config.twitchSecret,
    /*to be updated*/
    callbackURL: config.callbackURL,
    scope: "user_read"
  },
  function(accessToken, refreshToken, profile, done) {
    console.log(profile);
    ***return done();***
  }
));

答案 2 :(得分:3)

const ConditionalWrapper = ({ condition, wrapper, children }) => 
  condition ? wrapper(children) : children;

你想要包装的组件

<ConditionalWrapper
   condition={link}
   wrapper={children => <a href={link}>{children}</a>}>
   <h2>{brand}</h2>
</ConditionalWrapper>

也许这篇文章可以帮到你更多 https://blog.hackages.io/conditionally-wrap-an-element-in-react-a8b9a47fab2

答案 3 :(得分:1)

您还可以使用以下组件:conditional-wrap

  

一个简单的React组件,用于根据条件包装孩子。

答案 4 :(得分:1)

下面是一个我看过的有用组件的示例(不确定该组件由谁认可):

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

用例:


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


答案 5 :(得分:1)

还有另一种方法 您可以使用参考变量

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>

)

答案 6 :(得分:0)

您应该按照here所述使用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>
        )
    }
});

答案 7 :(得分:0)

您还可以使用如下所示的util函数:

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

答案 8 :(得分:-2)

一个功能组件,它呈现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>