【React 函数式组件知识点】

函数式组件的生命周期

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

javascript 复制代码
useEffect(() => {    
    // 类似于 componentDidMount    
    window.addEventListener('mousemove', () => {});        

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

useComponentWillMount 的实现

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

javascript 复制代码
const useComponentWillMount = (cb) => {    
    const willMount = useRef(true)    

    if (willMount.current) cb()    

    willMount.current = false
}

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

javascript 复制代码
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 函数,从而设置不同的值给一个对象

javascript 复制代码
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值并么有变化,则我们使用缓存的依赖项,如果子组件只依赖通过计算产生的依赖项,则就可以跳过子组件的重新渲染

相关推荐
福兮说8 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理9 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66610 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人10 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)10 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan11 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_11 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒11 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技12 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu12 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub