一、高阶组件:
高阶组件是参数为组件,返回值为新组件的函数
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式
解决问题:组件复用;
主要事项: 高阶组件的调用,不要在render方法中去调用const enhancer = Hoc(
,因为每次执行生成enhance都不一样,react在协调过程中去反复挂载卸载浪费性能,其次就是状态的丢失。
务必要复制被包装组件的静态方法:
// 定义静态函数
WrappedComponent.staticMethod = function() {}
// 现在使用HOC
const EnhancedComponent = enhance(WrappedComponent);
// 增强组件没有static Method
typeof EnhancedComponent.staticMethod === 'undefined' // true
解决方案:
1.返回之前务必把静态方法拷贝到目标容器上
function enhance(WrappedComponent) {
class Enhance extends React.Component {/*...*/}
// 必须准确知道应该拷贝哪些方法 :(
Enhance.staticMethod = WrappedComponent.staticMethod;
return Enhance;
}
import hoistNonReactStatic from 'hoist-non-react-statics';
function enhance(WrappedComponent) {
class Enhance extends React.Component {/*...*/}
hoistNonReactStatic(Enhance, WrappedComponent);
return Enhance;
}
2.另一个可行的方案是再额外导出这个静态方法
// 使用这种方式代替...
MyComponent.someFunction = someFunction;
export default MyComponent;
// ...单独导出该方法...
export { someFunction };
// ...并在要使用的组件中,import 它们
import MyComponent, { someFunction } from './MyComponent.js';
缺点并不会转发Ref:
虽然高阶组件的约定是将所有 props 传递给被包装组件,但这对于 refs 并不适用。那是因为 ref 实际上并不是一个 prop - 就像 key 一样,它是由 React 专门处理的。如果将 ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件
可以使用React.forwardRef进行传递:
Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧
React.forwardRef 接受一个渲染函数,其接收 props 和 ref 参数并返回一个 React 节点
function logProps(Component) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// 将自定义的 prop 属性 “forwardedRef” 定义为 ref
return ; }
}
// 注意 React.forwardRef 回调的第二个参数 “ref”。
// 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
// 然后它就可以被挂载到被 LogProps 包裹的子组件上。
return React.forwardRef((props, ref) => {
return ;
});
}
二、render props
1、什么是render prop:
具有render prop的组件接收一个函数,该函数返回一个React元素并调用它而不是实现自己的渲染逻辑;
2、render prop要解决的问题:
render prop 是一个用于告知组件需要渲染什么内容的函数prop;
使用 render prop 的库有 React Router、Downshift 以及 Formik。
如果想看更具体的实例请移步至官方实例看完之后再回到这里:
render prop是因为模式才被称为render prop而不是一定要用名称为render的prop;事实上任何用于告知组件需要渲染什么内容的函数prop在技术上都可以被称为render prop
}/>
// 内部调用
render() {
return({this.props.render(state)})
}
3、带render prop的常规组件可以实现大部分的高阶组件(Hoc)
function Hoc(Wrapped) {
return class extends React.Component{
render() {
return (
} />
)
}
}
}
4、 注意事项:render prop与React.PureComponent之间的问题:
如果在render里创建函数,那么在使用render prop的时候可能会抵消React.PureComponent带来的收益;这是因为浅比较props的时候总会得到false,每一个render对于render prop都会生成一个新值;
解决方案是定义一个prop作为实例方法:
renderProp = (state) =>
render() {
return ({this.props.render(state)})
}
三、自定义HOOK