HOC、Render props VS Hooks

前端技术江湖

共 5942字,需浏览 12分钟

 · 2021-01-13


工作中虽然在用react技术栈做开发,但react hooks 还没有实际用到,一直都在用redux。毕竟都2021了,如果还不会hooks真有点说不过去了,会怀疑我还是前端吗?

所以最近打算学习下 hooks。今天就记录一些浅显的理解,通过具体示例来感受下hooks的魅力。

个人理解

react hooks的作用:实现状态处理逻辑的封装,他是一个全新的API,彻底解决之前类组件中『状态处理逻辑』很难复用的问题,其实和render propshoc的功效是一样的。只不过hooks更彻底,更好用。

感受hooks的魅力

下面通过具体的代码示例来进行分析和理解、感受hooks的作用和魅力。

比如我们现在有个需求要实现两种产品列表,用于前后台展示。

前台产品列表

后台产品列表

常规的,类组件处理方式

看到上面的需求后,常规做法是会分别写两个组件,然后使用统一的产品列表api请求方法获取数据,然后处理状态。

前台产品列表组件

import React from 'react'
//产品列表api获取方法
import { getProductList } from '../../module/product'

export default class FrontProductList extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      proList: []
    }
  }

  componentDidMount() {
    getProductList().then(list => {
      this.setState({
        proList: list
      })
    })
  }

  render() {
    return "procardlist">

前台产品列表


      {this.state.proList.map(item => 
        

产品名称:{item.title}


        


        

价格:{item.price}


      
)}
    

  }


后台产品列表组件

import React from 'react'
import { getProductList } from '../../module/product'

//产品管理后台list
export default class AdminProductList extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      proList: []
    }
  }

  componentDidMount() {
    getProductList().then(list => {
      this.setState({
        proList: list
      })
    })
  }

  render() {
    return "procardlist">

管理员看到的产品列表


      
        
             
        
        {this.state.proList.map(item => 
          
          
          
        )}
      
产品名称产品简介价格

            {item.title}
          

            {item.des}
          

            {item.price}
          

    

  }


我们发现上面两个组件的状态处理逻辑是完全一致的,唯一不同的地方就是render部分。所以我们为了减少重复代码,使状态处理逻辑能够复用,会提取出两个组件无状态list组件,只用于渲染产品列表,且只接受一个props属性-proList(产品列表数据)。

前台产品列表组件

既然是无状态组件,直接使用函数组件即可

// FrontProductList.jsx
import React from 'react'

export default ({proList=[]}) => {
  return "procardlist">

前台产品列表


    {proList.map(item => 
      

产品名称:{item.title}

 

价格:{item.price}


    
)}
  

}

后台产品列表组件

//AdminProductList.jsx
import React from 'react'
import { getProductList } from '../../module/product'

//产品管理后台list
export default ({proList=[]})=> {
    return "procardlist">

后台产品列表


      
        
             
        
        {proList && proList.map(item => 
          
          
        )}
      
产品名称产品简介价格

            {item.title}
          

            {item.des}
          

    

那现在我们的状态处理组件就变成下面这样了。

//ProductData.jsx
import React from 'react'
import { getProductList } from '../../module/product'

export default class ProductData extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      proList: []
    }
  }

  componentDidMount() {
    getProductList().then(list => {
      this.setState({
        proList: list
      })
    })
  }
  //但我应该渲染哪个组件呢
  render() {
    return ?????
  }
}

但上面代码并没有写完,因为我们发现在render方法里我们不知道该渲染哪个列表组件?

使用render props

render props并不是什么新特性,只是一种函数调用模式而已,它可以把特定行为或功能封装成一个组件,提供给其他组件使用让其他组件也拥有这样的能力。而上面的问题就可以通过render props来解决。

说白了就是回调方法。

function GetList(callback){
 const list = getProductList()
    const result = callback(list)
    return reuslt
}

那对应到组件的实现方式想必你已经想到了。

//ProductData.jsx
import React from 'react'
import { getProductList } from '../../module/product'
export default class ProductData extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      proList: []
    }
  }

  componentDidMount() {
    getProductList().then(list => {
      this.setState({
        proList: list
      })
    })
  }
  //通过回调的方式来拿到要渲染的组件,父组件内部完全不需要知道渲染的是什么组件
  render() {
  return 
{
    this.props.render(this.state.proList)}

  }
}

调用方式

前台产品列表

}/> 

后台产品列表

}/> 

使用HOC

对于状态逻辑处理的复用,除了render props能做到,HOC也能做到,只是实现方式不同。

高阶组件的定义就不多说了,直接上代码。

import React from 'react'
import { getProductList } from '../../module/product'

//WrapperdComponent就是我们要渲染的产品列表组件

export default (WrapperdComponent)=>{
//ProductData 就是具有状态处理能力的组件
  return class ProductData extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        proList: []
      }
    }
  
    componentDidMount() {
      getProductList().then(list => {
        this.setState({
          proList: list
        })
      })
    }
    render() {
    //最终在这里渲染我们的列表组件
     return 
    }
  }

}

调用方式

前台产品列表

  ......
  const FrontProductList = ProductData(FrontProductList)
  ......
  render(){
   return 
  }

后台产品列表

  ......
  const AdminProductList = ProductData(AdminProductList)
  .....
  render(){
   return 
  }

使用hooks

上面我们使用render propsHOC这两种模式确实达到了状态处理逻辑复用的目的,那有没有更好的方式呢?

是时候表演真正的技术了。------ hooks闪亮登场。

先熟悉下,看下基于hooks的常规处理方式

//ProductList.jsx

import React from 'react'
import { getProductList } from '../../module/product'
import {useState,useEffect} from 'react'

export default function ProductList(){
  //获得产品列表数据
  const [proList,setProductList] = useState([])
  useEffect(()=>{
    getProductList().then(list => {
      setProductList(list)
    })
  },[])

  return "procardlist">

管理员看到的产品列表 - hooks


  
    
        
    
    {proList.map(item => 
      

      
    )}
  
产品名称产品简介

        {item.title}
      

        {item.des}
      



}

继续我们的菜, 在最开始我们提取出来的两个产品列表组件依然可用。

AdminProductList.jsx
FrontProductList.jsx

对于状态处理逻辑部分的复用方式,可以提取成自定义hooks

//useProductData.jsx

import React from 'react'
import { getProductList } from '../../module/product'
import {useState,useEffect} from 'react'

export default function useProductData(){
  const [proList,setProductList] = useState([])
  useEffect(()=>{
    getProductList().then(list => {
      setProductList(list)
    })
  },[])

  return proList //返回列表数据
}

调用方式

....
import useProductData from './components/ProductListHooks/useProductData'
import AdminProductList from './components/AdminProductList'
import FrontProductList from './components/FrontProductList'


function App(){
  const prolist = useProductData()
     return 
}

写到这里,不得不说hooks是真的香。

之前的逻辑复用只能是通过组件的方式来复用,代码多,上手成本也高。

而hooks直接突破,可以将状态处理逻辑直接封装成函数来进行调用。

小结

本文内容比较浅,所以咱们就浅显的看,其实react hooks就是几个api,这几个api调用都非常简单(只谈使用,原理后面再说),但可以实现完全使用函数组件达到原来类组件的效果,而且代码量少,不需要关心this,没有生命周期,最主要的是可以将状态处理逻辑封装成高度复用的函数,这是突破也是颠覆,更承认这是react的未来。

也许你已经习惯了类组件的开发方式,但就仅仅这种颠覆的逻辑复用方式,hooks就值得一试。

后面会用更多的代码示例来学习react hooks。

点个『在看』支持下 

浏览 17
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报