如何编写React Hook版HOC,在React Router v5中实现PageWrap(Account)路由配置
React Router v5 通用布局高阶组件改造方案
你当前的PageWrap是接收children的普通UI组件,而Route的component属性需要接收组件构造函数,不是JSX执行结果,直接调用PageWrap(Account)会返回JSX元素,不符合路由要求。需要将PageWrap改造成高阶组件(HOC):接收业务组件作为入参,返回被布局包裹后的新组件。
改造后代码(TS版本)
import styled from 'styled-components' import Footer from '../footer/Footer' import Header from '../header/Header' import React from 'react' // 入参为要包裹的业务组件 const PageWrap = <P extends object>(WrappedComponent: React.ComponentType<P>) => { // 返回被布局包裹的新组件,接收路由传递的所有属性 const WrappedPage: React.FC<P> = (props) => { return ( <> <Header /> <div className="other-small-comp"> {/* 透传所有属性(包含React Router5的history/location/match等路由属性)给业务组件 */} <WrappedComponent {...props} /> </div> <Footer /> </> ) } // 可选:设置displayName方便React DevTools调试 WrappedPage.displayName = `PageWrap(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})` return WrappedPage } export default PageWrap
改造后代码(JS版本)
import styled from 'styled-components' import Footer from '../footer/Footer' import Header from '../header/Header' import React from 'react' const PageWrap = (WrappedComponent) => { const WrappedPage = (props) => { return ( <> <Header /> <div className="other-small-comp"> <WrappedComponent {...props} /> </div> <Footer /> </> ) } WrappedPage.displayName = `PageWrap(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})` return WrappedPage } export default PageWrap
使用说明
你原本的路由配置不需要做任何改动,直接component={PageWrap(Account)}即可正常运行,路由属性会自动透传给Account组件。
注意事项
- 不要在组件render函数内执行
PageWrap(Account)生成组件,否则每次render都会生成新的组件实例,导致状态丢失、不必要的重渲染,建议在路由配置层提前生成包裹后的组件。 - 如果需要传递自定义属性给业务组件,可以扩展高阶组件入参,比如
PageWrap(Account, {title: '账户页'}),在内部透传给WrappedComponent即可。
内容的提问来源于stack exchange,提问作者angry kiwi
相关产品推荐
相关产品推荐

