Skip to content

8.高阶组件的使用 #8

@haokur

Description

@haokur

类似高阶函数,调用一个函数,传入一个函数,返回一个新的函数,高阶组件则是调用一个函数传入一个react组件,HOC不对传入组件的渲染逻辑进行修改,而是包裹原来的组件,为其新增props或行为,从而实现逻辑的复用和组件的抽象。

常用场景:

  • 给组件添加权限校验相关逻辑,比如决定是否渲染传入的组件
  • 如redux中的connect的方法,用于将store的数据链接传入到组件中
  • 给函数组件包装上类组件的错误捕获的两个方法,getDerivedStateFromError,componentDidCatch
  • 属性代理,类组件的反向继承

规范:

  • 函数命名方式,使用with开头
import React from 'react'

function withErrorBoundary(WrappedComponent: React.ComponentType<any>) {
    console.log("执行包装", "EffectCycle.tsx::10行");
    return class ErrorCatch extends React.Component {
        state = { hasError: false }
        constructor(props: any) {
            super(props)
        }

        static getDerivedStateFromError(error: Error) {
            console.log("捕获到错误", error, "EffectCycle.tsx::15行");
            return { hasError: true }
        }

        componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
            console.log(error, errorInfo)
        }

        render() {
            console.log("重新渲染:", this.state, "EffectCycle.tsx:r:23行");
            if (this.state.hasError) {
                return <h1>Something went wrong.</h1>
            }
            return <WrappedComponent{...this.props} />
        }
    }
}

export default withErrorBoundary
  • 外部使用
import { useState } from "react"
import { withErrorBoundary } from "../../hoc/with-error-boundary"

const HocTest = () => {
    const component = () => {
        const [arr, setArr] = useState([1, 2])
        const handleClick = () => {
            // @ts-ignore
            setArr(null)
        }
        return <div>
            {arr.map((item) => {
                return <div key={item}>
                    <div>{item}</div>
                </div>
            })}
            <button onClick={handleClick}>修改arr数据为null触发组件渲染错误</button>
        </div>
    }
    const WithErrorComponent = withErrorBoundary(component)

    return <div>
        <WithErrorComponent></WithErrorComponent>
    </div>
}
export default HocTest

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions