我建议将 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;
然后导入上述可复用的render prop组件,并通过TrackProduct传下来的props(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;
更多关于渲染道具的信息可以在Phoenix ReactJS conference talk找到。