react学习第四篇:HOC和自定义hook

2021-06-06  本文已影响0人  云鹤道人张业斌

概念:HOC参数为组件,返回值为新组件的函数,通过组件嵌套给子组件添加了更多功能

作用:1. 代码提取,组件复用。2.劫持被处理组件的生命周期

第一项:原逻辑

import React, {useContext} from "react";
import { appSetStateContext} from '../AppState'

export interface RobotProps {
  id: number;
  name: string;
  email: string;
}

// 组件传递数据使用的是props,接口定义传入的参数类型

const Robot: React.FC<RobotProps> = ({ id, name, email }) => {
  const setState = useContext(appSetStateContext)

  const addToCart = () => {
    if (setState) {
      setState(state => {
        return {
          ...state,
           shoppingCart: {
             items: [
              ...state.shoppingCart.items,
               {id, name}
             ]
           }
        }
      })
    }
  }
  return (
    <li>
        <button onClick={addToCart}>加入购物车</button>
      </li>
  );
};

export default Robot;

// FC functional component 函数式组件。FC默认有p = {}参数也就是props

第二项: 抽离业务代码之后

import React from "react";
1. 引入HOC
import {widthAddToCart} from './AddToCart'

2. 导出props的接口类型,HOC要用
export interface RobotProps {
  id: number;
  name: string;
  email: string;
//addToCart 是在HOC中新增的prop,这里要使用可选链标识不是必传的
  addToCart?: (id: number, name: string) => void
}

const Robot: React.FC<RobotProps> = ({ id, name, email, addToCart }) => {
  return (
    <li>
3. 通过props传过来的执行函数,执行并传入参数id,name
//由于props里面对addToCart使用了可选链,这里会提示addToCart可能是undefined,所以判断一下子
        <button onClick={() => addToCart && addToCart(id, name)}>加入购物车</button>
      </li>
  );
};
4. 使用HOC包裹组件
export default widthAddToCart(Robot);

新建AddToCart文件

// AddToCart.tsx
import React, {useContext} from 'react'
import {appSetStateContext} from '../AppState'
1. 引入组件的props的类型定义
import {RobotProps} from './Robot'


规范:一般使用width开头
2. 类型RobotProps给到ChildComponent
export const widthAddToCart = (ChildComponent: React.ComponentType<RobotProps>) => {
  // 返回类组件  return class extends React.Component {}
  // 或者返回函数式组件
  return (props:RobotProps) => {
    const setState = useContext(appSetStateContext)
  
    const addToCart = (id:number, name:string) => {
      if (setState) {
        setState(state => {
          return {
            ...state,
             shoppingCart: {
               items: [
                ...state.shoppingCart.items,
                 {id, name}
               ]
             }
          }
        })
      }
    }
  3. 将逻辑执行函数addToCart,通过导出组件的props传递出去
      return <ChildComponent {...props} addToCart={addToCart}/>
  }
}

自定义hook

  1. hook是函数
  2. 命名以use 开头
  3. 内部可以调用其他hook函数
  4. 并非React的特性
使用自定义hook实现代码的提取,实现复用

相对于使用HOC提取共用代码,自定义hook的优势:代码清晰简洁,hook是纯函数,代码更易维护

// AddToCart.tsx
将widthAddCart 改成 useAddToCart 
hook不需要引入React
import  {useContext} from 'react'
import {appSetStateContext} from '../AppState'

export const useAddToCart = () => {
  const setState = useContext(appSetStateContext)
  
    const addToCart = (id:number, name:string) => {
      if (setState) {
        setState(state => {
          return {
            ...state,
             shoppingCart: {
               items: [
                ...state.shoppingCart.items,
                 {id, name}
               ]
             }
          }
        })
      }
    }
    return addToCart
}

在组件中使用useAddToCart ,就比HOC更加简单

import {useAddToCart} from './AddToCart'

const Robot: React.FC<RobotProps> = ({ id, name, email }) => {
  const addToCart = useAddToCart()
  return (
    <li>
        <button onClick={() => addToCart(id, name)}>加入购物车</button>
      </li>
  );
};
上一篇下一篇

猜你喜欢

热点阅读