我有一个组件,有时需要渲染为
<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>
);
只需使用变量即可。
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 是与其他代码一样的代码。如果你想减少重复,请使用函数和变量。
创建一个 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>
);
这是我以前见过的有用组件的示例(不确定该将其授权给谁)。可以说它更具声明性:
const ConditionalWrap = ({ condition, wrap, children }) => (
condition ? wrap(children) : children
);
用例:
// MaybeModal will render its children within a modal (or not)
// depending on whether "isModal" is truthy
const MaybeModal = ({ children, isModal }) => {
return (
<ConditionalWrap
condition={isModal}
wrap={(wrappedChildren) => <Modal>{wrappedChildren}</Modal>}
>
{children}
</ConditionalWrap>
);
}
还有一个办法 你可以使用引用变量
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;
你想要包装的组件
<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
您还可以使用这样的 util 函数:
const wrapIf = (conditions, content, wrapper) => conditions
? React.cloneElement(wrapper, {}, content)
: content;
您应该使用 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 个组件,一个被包装,另一个没有。
// 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"}>
// 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>
使用反应和打字稿
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>
)
我个人正在使用这种代码(ComponentChildren是Preact,你应该能够使用ReactNode进行React):
const Parent = ({ children }: { children: ComponentChildren }) => props.link != null ?
<a href={ props.link }>{ children }</a> :
<>{ children }</>
return (
<Parent>
<i className={ styles.Icon }>
{ props.count }
</i>
</Parent>
)
提供的解决方案存在性能问题: https://medium.com/@cowi4030/optimizing-conditional-rendering-in-react-3fee6b197a20
React 将在下一次渲染时卸载
<Icon>
组件。
Icon
在 JSX 中以不同的顺序存在两次,如果您在下一次渲染时更改 props.link
,React 将卸载它。在这种情况下,<Icon>
它不是一个重组件,可以接受,但如果您正在寻找其他解决方案:
https://codesandbox.io/s/82jo98o708?file=/src/index.js
https://thoughtspile.github.io/2018/12/02/react-keep-mounted/