Я бы порекомендовал поднять Track
и ProductLink
в повторно используемый компонент - таким образом вы упростите его до одного условия.
Например:
import React from "react";
import PropTypes from "prop-types";
import Track from "./path/to/Track";
import ProductLink from "./path/to/ProductLink";
const TrackProduct = ({ children, isTracked }) => (
isTracked
? <Track>
<ProductLink>
{children}
</ProductLink>
</Track>
: children
);
TrackProduct.proptTypes = {
children: PropTypes.node.isRequired,
isTracked: PropTypes.bool.isRequired
};
export default TrackProduct;
Затем импортируйте вышеуказанный повторно используемый компонент и управляйте им с помощью state
:
import React from "react";
import TrackProduct from "./path/to/TrackProduct";
import Image from "./path/to/Image";
import Typography from "./path/to/Typography";
import Button from "./path/to/Button";
class Example extends Component {
state = { isTracked: false };
toggleTrack = () => this.setState(prevState => ({ track: !prevState.isTracked }))
render = () => (
<TrackProduct isTracked={this.state.isTracked}>
<Image ... />
<Typography ...>{...}</Typography>
<Typography ...>{...}</Typography>
<Button onClick={this.toggleTrack}>
{!this.state.isTracked ? "Track" : "Untrack"} Product
</Button>
</TrackProduct>
)
};
export default Example;
Если вышеприведенное не совсем работает и / или слишком повторяется, то вы можете использовать реквизит рендеринга, который передает некоторые из своих собственных полей состояния и класса в управляемую дочернюю функцию (я предпочитаю этот метод, а не HOC-оболочки, поскольку их легче проверять).
Например:
import React, { Component } from "react";
import PropTypes from "prop-types";
import Track from "./path/to/Track";
import ProductLink from "./path/to/ProductLink";
class TrackProduct extends Component {
state = { isTracked: false };
toggleTrack = () => this.setState(prevState => ({ track: !prevState.isTracked }))
render = () => {
const renderedChildren = this.props.children({
isTracked: this.state.isTracked,
toggleTrack: this.toggleTrack
});
return (
isTracked
? <Track>
<ProductLink>
{renderedChildren}
</ProductLink>
</Track>
: renderedChildren
)
};
};
TrackProduct.proptTypes = {
children: PropTypes.func.isRequired,
};
export default TrackProduct;
Затем импортируйте вышеупомянутый многократно используемый компонент рендеринга и управляйте им с помощью пропущенных реквизитов TrackProduct (isTracked
и toggleTrack
):
import React from "react";
import TrackProduct from "./path/to/TrackProduct";
import Image from "./path/to/Image";
import Typography from "./path/to/Typography";
import Button from "./path/to/Button";
const Example = () => (
<TrackProduct>
{({ isTracked, toggleTrack }) => (
<>
<Image ... />
<Typography ...>{...}</Typography>
<Typography ...>{...}</Typography>
<Button onClick={toggleTrack}>
{!isTracked ? "Track" : "Untrack"} Product
</Button>
</>
)}
</TrackProduct>
);
export default Example;
Более подробную информацию о реквизитах рендеринга можно найти в этом Феникс ReactJS конференц-разговор .