[React]用最简单的案例感受高阶组件

1,594 阅读3分钟

[理论]高阶组件 vs 高阶函数

首先,HOC高阶组件 vs 高阶函数:

高阶组件是:接受了一个组件作为参数,返回了另一个组件

高阶函数:接受一个函数作为参数,返回另一个函数

[理论]高阶组件的作用

复用组件逻辑

[实战] 处理空数据

在实际场景中,经常会出现一个问题就是,如果后端返回的字段,因为某些原因是null/空,那么页面上就不会展示。

为了防止数据展示的不好看,解决办法之一会是:将这些空字段统一替换成其他的,比如:‘空’ / ‘--’等。

每次在展示数据的时候,都遍历对象做空字符的替换,很累。

这个时候,我们就要复用“空字符的替换”的逻辑,写一个简单的高阶组件:

1. 需求:将空字符替换成‘--’

const withEmptyData = (WrappedComponent) => 新的组件

高阶组件:

const withEmptyData = (WrappedComponent) => {
    return class extends Component {
        handleProps = (props) => {
            const newProps = {...props};
            for (let key in props) {
                newProps[key] = props[key] === null ? '空' : props[key]
            }
            return newProps;
        }
        render() {
            return <WrappedComponent {...this.handleProps(this.props)}/>
        }
    }
}

如何使用:

const Item = ({name, age, address}) => {
    return (
        <div>
           name: {name} --- age:{age} --- address:{address}
        </div>
    )
}

const WithEmptyItem = withEmptyData(Item)

展示一个最新的组件:

const mockData = {
    name: 'rose',
    age: null,
    address: null
}

const Test = () => <WithEmptyItem {...mockData}/>

最终展示:

name:rose --- age: 空 --- address: 空

2. 需求:可以自定义当字段为空的时候显示的数据

const withEmptyData = (WrappedComponent, emptyText) => 新的组件

高阶组件:

const withEmptyData = (WrappedComponent, emptyText) => {
    return class extends Component {
        handleProps = (props) => {
            const newProps = {...props};
            for (let key in props) {
                newProps[key] = props[key] === null ? emptyText : props[key]
            }
            return newProps;
        }
        render() {
            return <WrappedComponent {...this.handleProps(this.props)}/>
        }
    }
}

如何使用:

const WithEmptyItem = withEmptyData(Item, '暂无数据')

最终展示:

name:rose --- age: 暂无数据 --- address: 暂无数据

3. 需求:双括号传参形式

const withEmptyData = emptyText => WrappedComponent => {}

还记得connect(mapState,mapDispatch)(Demo),这个也是一个高阶组件,这个两个括号的,我们的组件也可以改造成这个样子!

高阶组件:

const withEmptyData = emptyText => WrappedComponent => {
    return class extends Component {
        handleProps = (props) => {
            const newProps = {...props};
            for (let key in props) {
                newProps[key] = props[key] === null ? emptyText : props[key]
            }
            return newProps;
        }
        render() {
            return <WrappedComponent {...this.handleProps(this.props)}/>
        }
    }
}

如何使用:

const WithEmptyItem = withEmptyData('暂无数据')(Item)

[实战] 封装loading

当数据没有请求到之前,显示loading组件,当数据请求到了之后,显示正常的显示组件。

const withLoading = (WrappedComponent) =>{
    return class extends Component{
        render() {
            return this.props.loading ? <div>loading....</div> : <WrappedComponent {...this.props}/>
        }
    }
}
const LoadingItem = withLoading(Item)

特别简单!

[合并]高阶组件上面叠加高阶组件

这是可以的,既然上面两个需求,都是必须的,那么我们尝试的把他们叠加起来!用高阶组件叠加高阶组件的形式!

const withEmptyDataItem = withEmptyData('暂无数据')(Item)
const LoadingItem = withLoading(withEmptyDataItem)


const Test = () => <LoadingItem loading={loading} {...mockData}/>

这样,空字段的展示,和loading的功能都能用上啦!

最后,了解高阶组件的背景,了解到为什么会出现高阶组件的概念,可能会更有助于我们写代码的时候的选择用它,如何用它。

当然,实战也是必不可少的!