【React 函数式组件知识点】

函数式组件的生命周期

使用 useEffect 钩子函数可以模拟类组件的生命周期

useEffect(() => {    
    // 类似于 componentDidMount    
    window.addEventListener('mousemove', () => {});        

    return () => {        
        // 类似于 componentWillUnMount        
        window.removeEventListener('mousemove', () => {})    }
}, [])

useComponentWillMount 的实现

然而要模拟实现 componentWillMount,我们只能另辟蹊径,这里我们来手写一个 useComponentWillMount hook:

const useComponentWillMount = (cb) => {    
    const willMount = useRef(true)    

    if (willMount.current) cb()    

    willMount.current = false
}

值得注意的是,这并不能完全等同于 componentWillMount,因为存在代码顺序带来的问题,比如:

console.log('111')
useComponentWillMount(() => console.log('222'))
// output:
// 111
// 222

在这里,111 会在 useComponentWillMount 之前执行,而在 class 的 componentWillMount 中,是优先其他代码执行的。

因此,在实际开发中,我们要根据场景和需求,去灵活使用。

钩子函数详解

useEffect

在 React hook 中,useEffect 用来取代 componentDidMount 和 componentDidUpdate。主要作用是当页面渲染后,进行一些副作用操作(比如访问 DOM,请求数据)。

useLayoutEffect

useLayoutEffect 的出现是为了解决 useEffect 的页面闪烁问题。useEffect 是在组件挂载后异步执行的,并且执行事件会更加往后,如果我们在 useEffect 里面改变 state 状态,那么页面会出现闪烁(state 可见性变化导致的)。而 useLayoutEffect 是在渲染之前同步执行的,在这里执行修改 DOM 相关操作,就会避免页面闪烁的情况。

useCallback

useCallback 不是用来解决组件中有过多内部函数导致的性能问题

1.我们要知道,js创建一个函数的成本是非常小的,这点计算对于计算机来说是小case

2.其实使用useCallback会产成额外的性能:对deps的判断

3.其实每次组件重新渲染时,都无所谓避免重新创建内部函数,因为即使useCallback的deps没有变,它也会重新创建内部函数作为useCallback的实参

那么,它的作用到底是什么?useCallback的作用其实是用来避免子组件不必要的reRender:首先,假如我们不使用useCallback,在父组件中创建了一个名为handleClick的事件处理函数,根据需求我们需要把这个handleClick传给子组件,当父组件中的一些state变化后(这些state跟子组件没有关系),父组件会reRender,然后会重新创建名为handleClick函数实例,并传给子组件,这时即使用React.memo把子组件包裹起来,子组件也会重新渲染,因为props已经变化了,但这个渲染是无意义的.
对于这种deps不是经常变化的情况,我们用useCallback和React.memo的方式可以很好地避免子组件无效的reRender。但其实社区中对这个useCallback的使用也有争议,比如子组件中只是渲染了几个div,没有其他的大量计算,而浏览器去重新渲染几个dom的性能损耗其实也是非常小的,我们花了这么大的劲,使用了useCallback和React.memo,换来的收益很小,所以一些人认为就不用useCallback,就让浏览器去重新渲染好了。至于到底用不用,此处不深入讨论,我的建议是当子组件中的dom数量很多,或者有一些大量的计算操作,是可以进行这样的优化的。

useReducer

总的来说,useReducer是useState的复杂版,所有useState的规则,useReducer都适用。当我们需要对一个对象执行不同的操作时,可以用 useReducer,比如查询、重置、切换页码都在操作查询参数,这个时候我们就可以使用 useReducer,传一个 reducer 函数,在不同的操作里面执行 dispatch 函数,从而设置不同的值给一个对象

const initFormData = {
  name: "",
  age: 18,
  ethnicity: "汉族"
}
const reducer = (state, action) => {
  switch (action.type) {
    case 'patch': //更新
      return {...state, ...action.formData} //把旧的数据复制到一个对象,把新的数据复制到一个对象,把两个对象合并
    case "reset": //重置
      return initFormData
    default:
      throw new Error()
  }
}
const App = () => {
  console.log('App执行了一遍')
  const [formData, dispatch] = useReducer(reducer, initFormData)
  const onSubmit = () => {
  }
  const onReset = () => {
    dispatch({type: "reset"})
  }
  return (
    <form onSubmit={onSubmit} onReset={onReset}>
      <div>
        <label >
          姓名
          <input value={formData.name} onChange={e=>dispatch({type:"patch",formData:{name: e.target.value}})}/>
        </label>
      </div>
      <div>
        <label >
          年龄
          <input value={formData.age} onChange={e=>dispatch({type:"patch",formData:{age: e.target.value}})}/>
        </label>
      </div>
      <div>
        <label >
          民族
          <input value={formData.ethnicity} onChange={e=>dispatch({type:"patch",formData:{age: e.target.value}})}/>
        </label>
      </div>
      <div>
        <button type="submit">提交</button>
        <button type="reset">重置</button>
      </div>
      <hr/>
      {JSON.stringify(formData)}
    </form>
  )
}

useMemo

useMemo 是一个 React Hook,它在每次重新渲染的时候能够缓存计算的结果。它可以用来做下面的事情:

1、跳过代价昂贵的重新计算
2、跳过组件的重新渲染
3、记忆另一个 Hook 的依赖
4、记忆一个函数

默认情况下,当一个组件重新渲染时,React 会递归地重新渲染它的所有子组件,我们可以使用 useMemo 包裹需要大量计算而产生的依赖项,如果依赖项的props值并么有变化,则我们使用缓存的依赖项,如果子组件只依赖通过计算产生的依赖项,则就可以跳过子组件的重新渲染

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丢丢的大神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值