在我花在react上的时间和几篇文章上,我向自己询问我的自我如何重构hoc作为钩子,以及它是否有用,为什么,
这是重构的小部分
function withSpacing(Component) {
const WrappedWithSpacing = ({
pv, ph, pt, pb, pl, pr, style, ...props
}) => {
const styleWithSpacing = {};
const spacing = layout.padding;
const paddingTop = pt || pv;
const paddingBottom = pb || pv;
const paddingRight = pr || ph;
const paddingLeft = pl || ph;
if(paddingTop > 0) styleWithSpacing.paddingTop = paddingTop * spacing;
if(paddingBottom > 0) styleWithSpacing.paddingBottom = paddingBottom * spacing;
if(paddingLeft > 0) styleWithSpacing.paddingLeft = paddingLeft * spacing;
if(paddingRight > 0) styleWithSpacing.paddingRight = paddingRight * spacing;
return <Component style={{...style, ...styleWithSpacing}} {...props} />
}
WrappedWithSpacing.propTypes = {
pv: PropTypes.number,
ph: PropTypes.number,
pt: PropTypes.number,
pb: PropTypes.number,
pl: PropTypes.number,
pr: PropTypes.number,
style: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
}
WrappedWithSpacing.defaultProps = {
pv: 0,
ph: 0,
pt: 0,
pb: 0,
pr: 0,
pl: 0,
}
return WrappedWithSpacing;
}
export default withSpacing;
根据官方文件:
钩子是否更换渲染道具和高阶组件?
通常,渲染道具和高阶组件仅渲染一个 孩子。我们认为钩子是服务于此用例的更简单方法。那里 仍然是两种模式的地方(例如,虚拟滚动器 组件可能具有RenderItem Prop或视觉容器 组件可能具有自己的DOM结构(。但是在大多数情况下,钩子 足够了,可以帮助减少树的筑巢。
我使用此房屋只是为组件添加一些预定义的空间。
将其重构为钩子真的更好,您能解释一下我为什么吗?
如果是的,将其作为钩子重构的最佳方法是什么?
tdlr; 由于您的HOC没有任何状态或订阅,因此没有正当理由用钩子重构组件。
React Hooks介绍了几个新功能,以反应以补充其基于班级的对应物。useState
补充this.state
(文档(作为在渲染之间存储状态的功能方法。useEffect
补充了componentDidMount
和componenetDidUnmount
方法(DOCS(,该方法提供了执行功能性反应组件的设置和拆除的方法。
如果您从文档中进行了这样的事件:
// This function takes a component...
function withSubscription(WrappedComponent, selectData) {
// ...and returns another component...
return class extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
data: selectData(DataSource, props)
};
}
componentDidMount() {
// ... that takes care of the subscription...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... and renders the wrapped component with the fresh data!
// Notice that we pass through any additional props
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
并将其转换为功能组件,您可能最终会得到类似的内容:
function withSubscription(WrappedComponent, selectData) {
return function WrappedComponent (props) {
const [myData, setMyData] = useState(null);
useEffect(() => {
const handleMyDataChange = newData => {
setMyData(newData);
}
DataSource.addChangeListener(handleMyDataChange);
return function cleanup() {
DataSource.removeChangeListener(handleMyDataChange);
};
});
return <WrappedComponent data={data} {...this.props} />;
}
您的填充和间距会在每个渲染上重新生成。由于您在问题中拥有的代码没有任何在渲染之间持续存在的任何内容,因此尝试将其重构为实现React Hooks的组件是没有多大意义的。React Hooks更适合将基于类的反应组件转换为功能性反应组件。