[英]How do I conditionally wrap a React component?
I have a component that will sometimes need to be rendered as an <anchor>
and other times as a <div>
.我有一个组件,有时需要呈现为
<anchor>
,有时需要呈现为<div>
。 The prop
I read to determine this, is this.props.url
.我为确定这一点而阅读的
prop
是this.props.url
。
If it exists, I need to render the component wrapped in an <a href={this.props.url}>
.如果存在,我需要渲染包装在
<a href={this.props.url}>
中的组件。 Otherwise it just gets rendered as a <div/>
.否则它只会被渲染为
<div/>
。
Possible?可能的?
This is what I'm doing right now, but feel it could be simplified:这就是我现在正在做的事情,但觉得它可以简化:
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>
);
Here is the final lockup.这是最后的锁定。 Thanks for the tip, @Sulthan !
感谢您的提示, @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;
}
}
Just use a variable.只需使用一个变量。
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;
or, you can use a helper function to render the contents.或者,您可以使用辅助函数来呈现内容。 JSX is code like any other.
JSX 和其他代码一样。 If you want to reduce duplications, use functions and variables.
如果要减少重复,请使用函数和变量。
Create a HOC (higher-order component) for wrapping your element:创建一个 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>
);
Here's an example of a helpful component I've seen used before (not sure who to accredit it to) which might be more declarative:这是我以前见过的一个有用组件的示例(不确定该授权给谁),它可能更具声明性:
const ConditionalWrap = ({ condition, wrap, children }) => (
condition ? wrap(children) : children
);
Use case:用例:
// This children of this MaybeInAModal component will appear as-is or within a modal
// depending on whether "shouldOpenInModal" is truthy
const MaybeInAModal = ({ children, shouldOpenInModal }) => {
return (
<ConditionalWrap
condition={shouldOpenInModal}
wrap={wrappedChildren => (<Modal>{wrappedChildren}</Modal>)}
{children}
</ConditionalWrap>
);
}
There's another way you could use a reference variable还有另一种方法可以使用引用变量
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>
)
const ConditionalWrapper = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children;
The component you wanna wrap as您要包装的组件
<ConditionalWrapper
condition={link}
wrapper={children => <a href={link}>{children}</a>}>
<h2>{brand}</h2>
</ConditionalWrapper>
Maybe this article can help you more https://blog.hackages.io/conditionally-wrap-an-element-in-react-a8b9a47fab2也许这篇文章可以帮助你更多https://blog.hackages.io/conditionally-wrap-an-element-in-react-a8b9a47fab2
You could also use this component: conditional-wrap 您也可以使用此组件: conditional-wrap
A simple React component for wrapping children based on a condition.
一个简单的React组件,用于根据条件包装子项。
You should use a JSX if-else as described here .您应该使用此处描述的 JSX if-else。 Something like this should work.
像这样的东西应该工作。
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>
)
}
});
You could also use a util function like this:您还可以使用这样的 util 函数:
const wrapIf = (conditions, content, wrapper) => conditions
? React.cloneElement(wrapper, {}, content)
: content;
Using react and Typescript使用反应和打字稿
let Wrapper = ({ children }: { children: ReactNode }) => <>{children} </> if (this.props.link) { Wrapper = ({ children }: { children: ReactNode }) => <Link to={this.props.link}>{children} </Link> } return ( <Wrapper> <i> {this.props.count} </i> </Wrapper> )
A functional component which renders 2 components, one is wrapped and the other isn't.一个功能组件,它呈现 2 个组件,一个被包装,另一个没有。
// 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>
This can also be used like this:这也可以像这样使用:
<WrapIf condition={true} With={"h1"}>
// 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>
With provided solutions there is a problem with performance: https://medium.com/@cowi4030/optimizing-conditional-rendering-in-react-3fee6b197a20提供的解决方案存在性能问题: https ://medium.com/@cowi4030/optimizing-conditional-rendering-in-react-3fee6b197a20
React will unmount <Icon>
component on the next render. React 将在下一次渲染时卸载
<Icon>
组件。 Icon
exist twice in different order in JSX and React will unmount it if you change props.link
on next render. Icon
在 JSX 中以不同的顺序存在两次,如果您在下次渲染时更改props.link
,React 将卸载它。 In this case <Icon>
its not a heavy component and its acceptable but if you are looking for an other solutions:在这种情况下,
<Icon>
它不是一个沉重的组件并且可以接受,但是如果您正在寻找其他解决方案:
https://codesandbox.io/s/82jo98o708?file=/src/index.js https://codesandbox.io/s/82jo98o708?file=/src/index.js
https://thoughtspile.github.io/2018/12/02/react-keep-mounted/ https://thoughtspile.github.io/2018/12/02/react-keep-mounted/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.