我目前有一个HOC组件,我想移植它以使用react挂钩,并且基本上只是开始考虑这个想法。
此HOC组件基本上为包装的组件提供了显示警报对话框的功能。 HOC组件管理自己的状态,这使得包装的组件非常容易显示警报对话框。包装的组件只需调用传递给props的函数来显示它。
HOC现在是这样的:
function withAlertDialog(WrappedComponent) {
return class extends Component {
constructor(props) {
super(props);
this.state = {
alertDialogOpen: false,
alertMessage: ""
};
}
displayAlert = message => {
this.setState({alertDialogOpen: true, alertMessage: message});
}
closeAlertDialog = () => {
this.setState({alertDialogOpen: false});
}
render() {
return (
<React.Fragment>
<WrappedComponent
onDisplayAlert={this.displayAlert}
onCloseAlert={this.closeAlertDialog} />
<MyAlertDialogComponent
open={this.state.alertDialogOpen}
onClose={this.closeAlertDialog} />
</React.Fragment>
);
}
}
}
这是一个更简单的情况,实际使用的HOC要复杂得多,但是这个想法仍然存在。现在,已包装的组件基本上可以调用this.props.onDisplayAlert('some message here');
来显示警报。包装的组件也不必在自己的渲染函数中渲染MyAlertDialogComponent
。基本上,包装的组件不必担心MyAlertDialogComponent
的处理方式,它所知道的就是调用this.props.onDisplayAlert
会以某种方式显示一个警告对话框。重用此HOC可以节省很多代码。
如何将其更改为react hooks实现?我已经尝试过环顾四周,但是大多数文章和文档本身使用的是带有单个包装组件的HOC,除此之外,实际上并没有管理其他组件。我想了解如何更改为“反应挂钩”的思想,但保持相同的方便程度,不必在要使用它的每个组件中呈现MyAlertDialogComponent
。
答案 0 :(得分:0)
旧的HOC和使用钩子的新HOC之间的唯一区别是,您只需要将从HOC返回的匿名类更改为使用钩子的匿名函数。
类和挂钩函数之间的转换遵循正常的转换规则,您可能会在许多在线教程中找到这些规则。以您的示例为例,将状态转换为useState
并将类方法转换为常规函数。
您只需将状态和这些常规功能传递给需要它们的任何组件。调用您所在州的setter将会重新渲染该组件。
如果您查看下面的示例,您将看到MyWrappedComponent
被withAlertDialog
包装,该包装将两个功能道具传递给MyWrappedComponent
。这些功能在MyWrappedComponent
内部使用,以设置呈现MyAlertDialogComponent
const { useState } = React
function withAlertDialog(WrappedComponent) {
return function(props){
const [alertState, setAlertState] = useState({
alertDialogOpen: false,
alertMessage: ""
})
const displayAlert = message => {
setAlertState({
alertDialogOpen: true,
alertMessage: message
});
}
const closeAlertDialog = () => {
setAlertState({alertDialogOpen: false});
}
return (
<React.Fragment>
<WrappedComponent
onDisplayAlert={displayAlert}
onCloseAlert={closeAlertDialog} />
<MyAlertDialogComponent
open={alertState.alertDialogOpen}
onClose={closeAlertDialog} />
</React.Fragment>
);
}
}
const MyWrappedComponent = withAlertDialog(function (props){
return (
<div>
<a onClick={props.onDisplayAlert}>Open Alert</a>
<a onClick={props.onCloseAlert}>Close Alert</a>
</div>
)
})
function MyAlertDialogComponent(props){
if(!props.open){
return null
}
return (
<div>Dialogue Open</div>
)
}
function App(){
return (
<MyWrappedComponent />
)
}
ReactDOM.render(<App />, document.querySelector('#app'))
div > a {
display : block;
padding : 10px 0;
}
<div id="app" />
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>