Tengo un componente que a veces necesitará renderizarse como an <anchor>
y otras veces como <div>
. El prop
que leí para determinar esto, es this.props.url
.
Si existe, necesito renderizar el componente envuelto en un <a href={this.props.url}>
. De lo contrario, simplemente se renderiza como <div/>
.
¿Posible?
Esto es lo que estoy haciendo ahora mismo, pero creo que podría simplificarse:
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>
);
ACTUALIZAR:
Aquí está el bloqueo final. ¡Gracias por el consejo, @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;
}
}
javascript
reactjs
Brandon Durham
fuente
fuente
const baseClasses =
a esaif (this.props.link)
rama. Como está usando ES6, también puede simplificar un pococonst {link, className} = this.props;
y luego usarlink
yclassName
como variables locales.Respuestas:
Solo usa una 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;
o puede utilizar una función auxiliar para representar el contenido. JSX es un código como cualquier otro. Si desea reducir las duplicaciones, use funciones y variables.
fuente
Cree un HOC (componente de orden superior) para envolver su elemento:
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> );
fuente
HOC
es espantoso. Es simplemente una función que se coloca en el medio. Realmente desplazo este nombre repentinamente de moda "HPC". lo que es tan importante en una función simple que se coloca en el medio ... concepto antiguo durante décadas.Aquí hay un ejemplo de un componente útil que he visto utilizado (no estoy seguro de a quién acreditarlo) que hace el trabajo:
const ConditionalWrap = ({ condition, wrap, children }) => ( condition ? wrap(children) : children );
Caso de uso:
<ConditionalWrap condition={someCondition} wrap={children => (<a>{children}</a>)} // Can be anything > This text is passed as the children arg to the wrap prop </ConditionalWrap>
fuente
wrap
declarativamente y no como una función para mantener las cosas más "React" -spiritHay otra forma de usar una variable de referencia
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> )
fuente
let Wrapper = someCondition ? ParentComponent : React.Fragment
React.Fragment can only have 'key' and 'children'
porque paso algunos accesorios a "<Wrapper>" como "className" y asíTambién puede usar una función útil como esta:
const wrapIf = (conditions, content, wrapper) => conditions ? React.cloneElement(wrapper, {}, content) : content;
fuente
Debe usar un JSX if-else como se describe aquí . Algo como esto debería funcionar.
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> ) } });
fuente
Un componente funcional que presenta 2 componentes, uno está empaquetado y el otro no.
Método 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>
Esto también se puede usar así:
<WrapIf condition={true} With={"h1"}>
Método 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>
fuente