这篇文章主要介绍了React高阶组件怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇React高阶组件怎么使用文章都会有所收获,下面我们一起来看看吧。
高阶组件也就是我们常说的HOC,是React中用于复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分,他是一种基于React的组合特性而形成的设计模式。
其实就是组件作为参数,返回值也是组件的函数,他是纯函数,不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC通过将组件包装在容器组件中来组成新组件。HOC是纯函数,没有副作用。
抽取重复代码,实现组件复用:相同功能组件复用
条件渲染,控制组件的渲染逻辑(渲染劫持):权限控制
捕获/劫持被处理组件的生命周期,常见场景:组件渲染性能追踪、日志打点。
先来看一个简单的HOC实现方式
function withLog(Component) { return function (props) { console.log(`[${new Date().toISOString()}] ${Component.name} props:`, props); return <Component {...props} />; }; }
这个HOC接收一个组件作为参数,返回一个新的组件,新的组件在渲染之前会先输出当前时间和传入的组件的名称和props到控制台,然后再将props传递给原始组件进行渲染。
使用这个HOC可以像下面这样
function MyComponent(props) { return <div>{props.message}</div>; } const MyComponentWithLog = withLog(MyComponent); ReactDOM.render( <MyComponentWithLog message="Hello, world!" />, document.getElementById('root') );
渲染的时候控制台会输出
[2023-04-16T00:00:00.000Z] MyComponent props: { message: "Hello, world!" }
可以看到,HOC 可以用来增强组件的功能,比如添加日志、添加权限校验、添加数据预处理等。
其实HOC的实现方式主要分为两种:属性代理和反向继承
使用组合的方式,将组件包装在容器上,依赖父子组件的生命周期关系来:
返回无状态的函数组件
返回class组件
操作props
// 可以通过属性代理,拦截父组件传递过来的porps并进行处理。 // 返回一个无状态的函数组件 function HOC(WrappedComponent) { const newProps = { type: 'HOC' }; return props => <WrappedComponent {...props} {...newProps}/>; } // 返回一个有状态的 class 组件 function HOC(WrappedComponent) { return class extends React.Component { render() { const newProps = { type: 'HOC' }; return <WrappedComponent {...this.props} {...newProps}/>; } }; }
抽象state
通过属性代理无法直接操作原组件的state,可以通过props和回调函数抽象state
function HOC(WrappedComponent) { return class extends React.Component { constructor(props) { super(props); this.state = { name: '', }; this.onChange = this.onChange.bind(this); } onChange = (event) => { this.setState({ name: event.target.value, }) } render() { const newProps = { name: { value: this.state.name, onChange: this.onChange, }, }; return <WrappedComponent {...this.props} {...newProps} />; } }; } // 使用 @HOC class Example extends Component { render() { return <input name="name" {...this.props.name} />; } }
这里我们稍微做一下解释。我们主要的目的是想通过传给HOC的这个组件来修改HOC的state,在HOC中定义了onChange方法目的是可以修改state。如果在WrappedComponent中调用onChange方法呢?我们可以定义一个对象作为WrappedComponent的props,然后将onChange方法存储在定义的对象上,传给WrappedComponent。
在WrappedComponent中,我们定义了一个input,我们都知道input有value属性作为input的值,还有一个onChange方法作为change事件,我们把传给WrappedComponent的props结构刚好就是value和onChange。这样当input在change的时候就可以就修改state的值了。
通过props实现条件渲染
通过props来控制是否渲染及传入数据
import * as React from 'react'; function HOC (WrappedComponent) { return (props) => ( <div> { props.isShow ? ( <WrappedComponent {...props} /> ) : <div>暂无数据</div> } </div> ); } export default HOC;
其他元素wrapper传入的组件
function withBackgroundColor(WrappedComponent) { return class extends React.Component { render() { return ( <div style={{ backgroundColor: '#ccc' }}> <WrappedComponent {...this.props} {...newProps} /> </div> ); } }; }
使用一个函数接收一个组件作为参数传入,并返回一个继承了该传入组件的类组件,且在返回组件的render()
方法中返回了super.render()
方法。
const HOC = (WrappedComponent) => { return class extends WrappedComponent { render() { return super.render() } } }
允许HOC通过this访问到原组件,可以直接读取和操作原组件的state/ref等
可以通过render.super()
获取传入组件的render,可以有选择的渲染劫持
劫持原组件生命周期方法
function HOC(WrappedComponent){ const didMount = WrappedComponent.prototype.componentDidMount; // 继承了传入组件 return class HOC extends WrappedComponent { async componentDidMount(){ // 劫持 WrappedComponent 组件的生命周期 if (didMount) { await didMount.apply(this); } ... } render(){ //使用 super 调用传入组件的 render 方法 return super.render(); } } }
读取/操作原组件的state
function HOC(WrappedComponent){ const didMount = WrappedComponent.prototype.componentDidMount; // 继承了传入组件 return class HOC extends WrappedComponent { async componentDidMount(){ if (didMount) { await didMount.apply(this); } // 将 state 中的 number 值修改成 2 this.setState({ number: 2 }); } render(){ //使用 super 调用传入组件的 render 方法 return super.render(); } } }
通过this.setState({ number: 2 });
修改了原组件WrappedComponent
中的state的number值
条件渲染
const HOC = (WrappedComponent) => class extends WrappedComponent { render() { if (this.props.isRender) { return super.render(); } else { return <div>暂无数据</div>; } } }
修改react树
// 修改返回render结果 function HigherOrderComponent(WrappedComponent) { return class extends WrappedComponent { render() { const tree = super.render(); const newProps = {}; if (tree && tree.type === 'input') { newProps.value = 'something here'; } const props = { ...tree.props, ...newProps, }; const newTree = React.cloneElement(tree, props, tree.props.children); return newTree; } }; }
这里首先通过super.render()
拿到需要渲染的树,然后对这个渲染树做了修改。比如如果是一个input,则修改它的value值。
属性代理:从"组合"角度出发,有利于从外部操作WrappedComponent,可以操作props,或者在WrappedComponent外加一些拦截器(如:条件渲染,增加外部样式)
反向继承:从"继承"角度出发,从内部操作WrappedComponent,可以操作组件内部的state,生命周期和render等,功能更强大
关于“React高阶组件怎么使用”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“React高阶组件怎么使用”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。