Mam komponent, który czasami trzeba będzie renderować jako plik, <anchor>
a innym razem jako plik <div>
. prop
Czytam w celu ustalenia tego jest this.props.url
.
Jeśli istnieje, muszę wyrenderować komponent opakowany w plik <a href={this.props.url}>
. W przeciwnym razie zostanie po prostu renderowany jako plik <div/>
.
Możliwy?
Oto, co teraz robię, ale czuję, że można to uprościć:
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>
);
AKTUALIZACJA:
Oto ostateczne zamknięcie. Dzięki za wskazówkę, @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
źródło
źródło
const baseClasses =
do tejif (this.props.link)
gałęzi. Ponieważ używasz ES6, możesz także nieco uprościć,const {link, className} = this.props;
używająclink
iclassName
jako zmiennych lokalnych.Odpowiedzi:
Po prostu użyj zmiennej.
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;
lub możesz użyć funkcji pomocniczej do renderowania zawartości. JSX to kod jak każdy inny. Jeśli chcesz zredukować powielanie, użyj funkcji i zmiennych.
źródło
Utwórz HOC (komponent wyższego rzędu) do pakowania elementu:
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> );
źródło
HOC
jest ohydny. To tylko funkcja umieszczona pośrodku. Naprawdę wypieram tę nagle modną nazwę „HPC”. co jest tak ważnego w prostej funkcji, która jest umieszczona pomiędzy ... starą koncepcją od dziesięcioleci.Oto przykład przydatnego komponentu, z którego korzystałem (nie wiem, komu go akredytować), który spełnia swoje zadanie:
const ConditionalWrap = ({ condition, wrap, children }) => ( condition ? wrap(children) : children );
Przypadek użycia:
<ConditionalWrap condition={someCondition} wrap={children => (<a>{children}</a>)} // Can be anything > This text is passed as the children arg to the wrap prop </ConditionalWrap>
źródło
wrap
deklaratywnego, a nie funkcji, aby zachować bardziej "Reagowanie" -spiritIstnieje inny sposób użycia zmiennej referencyjnej
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> )
źródło
let Wrapper = someCondition ? ParentComponent : React.Fragment
React.Fragment can only have 'key' and 'children'
Możesz również użyć funkcji util, takiej jak ta:
const wrapIf = (conditions, content, wrapper) => conditions ? React.cloneElement(wrapper, {}, content) : content;
źródło
Powinieneś użyć JSX if-else, jak opisano tutaj . Coś takiego powinno działać.
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> ) } });
źródło
Funkcjonalny komponent, który renderuje 2 komponenty, jeden jest opakowany, a drugi nie.
Metoda 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>
Można tego również użyć w następujący sposób:
<WrapIf condition={true} With={"h1"}>
Metoda 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>
źródło