React Hooks

1、class 组件的问题?

  • 大型组件很难拆分和重构,难测试
  • 相同业务逻辑,分散到各个方法中,逻辑比较混乱
  • 复用逻辑变得复杂,如Minxins 、HOC、Render Prop

所以react 提倡函数式编程,因为函数更灵活、更易拆分、更容易测试,但是函数太简单,但是函数组件加上hooks就能实现class 里的功能。

2、 useEffect 模拟组件的生命周期?

  • 模拟componentDidMount 和componentDidUpdate
useEffect(()=>{
 // 这是模拟的加载完和更新完的生命周期
 
})
  • 模拟 componentDidMount
useEffect(()=>{
 // 这是模拟的加载完,加载完了
},[])
  • 模拟componentDidUpdate
useEffect(()=>{
 // 这是模拟componentDidUpdate 更新完了
},[data1,data2])
  • 模拟销毁的时候 componentWillUnmount
useEffect(()=>{
let timer = setInertval(()=>{
 console.log('打印')
},1000)
// 模拟componentWillUnmount,就是return
// 只有当不传任何参数或依赖空数组,当props发生变化,也会执行销毁函数里的代码;也就是说销毁函数会在下一次执行effect之前执行
return ()=>{
clearInterval(timer)
 }
},[])

useEffect 让纯函数有了副作用
在这里插入图片描述

1、useEffect 模拟componentWillUnMount 生命周期的注意事项

  • useEffect 依赖于[](空数组)的时候,组件销毁就会执行return 返回的函数,就相当于组件销毁前componentWillUnMount生命周期
  • useEffect 无依赖或依赖【a,b】,组件更新时也会执行return返回的函数,即 不过获取的值是上一次执行useEffect 的a,b的值。也就是return 的函数会在下一次useEffect执行之前执行
    在这里插入图片描述
    在这里插入图片描述

3、useRef 获取dom节点

在这里插入图片描述

4、useContext 组件之间共享状态,只存在于Context包裹下的所有子孙组件

父组件:

const houseDetailsData:HouseDetailsData = {
  basic:{jyrxx:[], glrxx:[],fyzpxx:[]},
  record:[]
}
// 创建一个context ,给他一个初始值
export const HouseDetailsContext = React.createContext(houseDetailsData)

{/**使用刚才命名的HouseDetailsContext.Provider 包裹你需要传给的子孙组件,把值传进去之后,他包裹的所有组件都可以使用houseDetailsInfo值 */}
 <HouseDetailsContext.Provider value={houseDetailsInfo}>
   <HouseDetails></HouseDetails>
 </HouseDetailsContext.Provider>

然后子孙组件使用的话:

import React, { useContext } from 'react';
// 引入你刚才定义的Context 变量
import { HouseDetailsContext } from './index'
 // 使用useContext就可以使用上级传下来的值
 const houseDetailsData = useContext(HouseDetailsContext)
 <div>{houseDetailsData.name}</div>

这样子就是一个useContext的基本使用

5、useReducer 和redux的区别?

  • useReducer是useState的代替方案,用于state的复杂变化,借鉴了redux的实现方式
  • useReducer是单个组件状态管理,组件通讯还是需要props
  • redux 是全局状态管理,多组件共享数据
  • 所以useReducer 和redux 不是一个东西,只不过useReducer借鉴了redux实现方式而已。
import React, { useReducer } from 'react'

const initialState = { count: 0 }
const reducer = (state, action) => {
  switch (action) {
    case 'add':
      return { count: state.count + 1 }
    case 'dele':
      return { count: state.count - 1 }
    default:
      return state
  }
}

const UseReducerDemo = () => {
  const [state, dispatch] = useReducer(reducer, initialState)
  return (
    <>
      值:{state}
      <button onClick={() => dispatch('add')}>增加</button>
      <button onClick={() => dispatch('dele')}>减少</button>
    </>
  )
}
export default UseReducerDemo

6、使用useMemo 做性能优化

场景:当父组件更新,子组件依赖的属性并没有变化,不想子组件也更新,可用这个做优化

  • 父组件更新所有的子组件默认更新
  • class组件使用scu 和superComponent做优化
  • hooks 中使用useMemo,原理都是相同的,都是对依赖的变量进行浅层对比

父组件使用useMemo包裹住你想判断的变量,这些变量改变的话,才会重新渲染子组件,使用useMemo缓存数据

import React, { useState, useMemo } from 'react'
import ChangeName from './ChangeName'

const UseReducerDemo = () => {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('lisi')
  // const useInfo = { name, age: 20 }
  // name是我监听的变量,只有这个变量改变了我的字组件才会重新渲染
  const useInfo = useMemo(() => {
    return { name, age: 20 }
  }, [name])
  return (
    <>
      值:{count}
      <button onClick={() => setCount(count + 1)}>增加</button>
      <ChangeName info={useInfo} />
    </>
  )
}
export default UseReducerDemo

子组件就是用memo来包裹住整个子组件,写法如下:

import React, { memo } from 'react'


const ChangeName = memo((props) => {
  const { info } = props
  return (
    <>
      <div>名字:{info.name} --- 年龄:{info.age}</div>
    </>
  )
})
export default ChangeName

7、使用useCallback做性能优化

  • useCallback用来缓存函数,需要跟memo来配合,如果父组件向子组件传入一个函数,不用useCallback来包裹,那么父组件更新,子组件一样会更新
  • useMemo用来缓存数据
  • 这两种就是react hook 常用性能优化方案
    父组件使用useCallback
	import React, { useState, useMemo, useCallback } from 'react'
import ChangeName from './ChangeName'

const UseReducerDemo = () => {
  const [count, setCount] = useState(0)
  const [name, setName] = useState('lisi')
  // const useInfo = { name, age: 20 }
  const useInfo = useMemo(() => {
    return { name, age: 20 }
  }, [name])
  // 使用useCallback来缓存函数
  const onchange = useCallback((e) => {
    console.log('e', e.taget.value)
  }, [])
  return (
    <>
      值:{count}
      <button onClick={() => setCount(count + 1)}>增加</button>
      <ChangeName useInfo={useInfo} onchange={onchange} />
    </>
  )
}
export default UseReducerDemo

子组件接收

import React, { memo } from "react";

const ChangeName = memo((props) => {
  const { useInfo, onchange } = props;
  console.log(props);
  return (
    <>
      <div>
        名字:{useInfo.name} --- 年龄:{useInfo.age}
      </div>
      <input onChange={onchange} />
    </>
  );
});
export default ChangeName;

8、自定义hook

  • 封装通用的功能
  • 自定义hook带来了无限的扩展性,解耦代码
  • 本质是一个函数,以use开头
  • 自定义hook内部可以使用useState、useEffect或者其他的hooks
  • 自定义返回结果,格式不限
    场景:封装axios,useAxios

9、 使用hooks的两条重要规则

  • useXxx 的命名规范

1、 hooks 的使用规范

  • 只能用于react函数组件和自定义hooks中,其他地方不可以使用(class组件不能、函数不能)
  • 只能用于顶层代码,不能在循环、判断中使用hooks
  • eslint 插件 eslint-plugin-react-hooks帮助你

2、为何hooks 要依赖于调用顺序?

  • 无论是组件初始化还是组件更新,hooks的调用顺序必须一致
  • 如果hooks 中出现判断或者循环则无法保证顺序的一致。
  • hooks 严重依赖于调用顺序
    在这里插入图片描述

10 、class 组件逻辑复用的问题

  • 高阶组件:

    • 组件层级嵌套过多,不易渲染,不易调试
    • HOC会劫持props,必须严格规范,容易出现疏漏
  • Render Props:

    • 学习成本高,不易理解
    • 只能传递纯函数,而默认情况下纯函数功能有限

11、使用react hooks 来进行组件逻辑复用有哪些好处

  • 完全符合hooks原有规则,没有其他要求,易理解
  • 变量作用域很明确
  • 不会产生组件嵌套

12、react hooks 有哪些注意事项(坑)?

  • useState 初始化值,只有第一次有效。重新渲染时只恢复初始化的state值,不会再重新设置新的值,如果想要修改,只能使用setSate修改值;例如父组件向子组件传递一个属性,子组件初始化的useState是父组件的值,当父组件改变那个属性,子组件state不会发生改变
    -在这里插入图片描述

  • useEffect 依赖为【】的时候,重新渲染不会执行effect 函数,所以在里面修改state值无效;如果useEffect 没有依赖,重新渲染会执行effect函数,修改state值有效,解决方案如下:
    在这里插入图片描述

  • 解决,在外层定义一个useRef
    在这里插入图片描述

  • useEffect 可能会出现死循环,在useEffect 依赖是一个数组或者对象的时候,可能会出现死循环。解决办法就是将对象打散变成一个值类型,在里面进行重组
    在这里插入图片描述

  • 原因是useEffect用来判断依赖是否发生改变是用的object.is,,来进行判断,当是对象和数组时返回的都是false,不一样,所以一直会循环
    在这里插入图片描述

13、react hooks 做组件复用的优点?

  • 变量作用域明确
  • 不会产生组件嵌套
  • 完全符合hooks原有原则,没有其他要求,易理解记忆
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值