React Hooks 实践分享

397 阅读3分钟

React Hooks 它可以让你在函数组件中使用 React 的特性,不再需要使用面向对象的编程范式来编写 Class 组件,恢复 Javascript 灵活的语言特性。

IMPORTANT
在函数组件中,所有变量和函数必须用 Hooks 包起来。直接声明变量或函数,会使性能变差。

ref

对于函数组件,如果想通过 props 传入 ref,组件就必须使用 forwardRef。使用了 forwardRef,组件在调试工具中显示的名称会变成匿名,会导致调试难度变大,所以需要设置组件的 displayName 属性。一个完整的组件模板如下:

import React, { forwardRef } from 'react'

const Component = forwardRef(({ /* props */ }, ref) => {
  return <></>
})

Component.displayName = 'ComponentName'

Component.propTypes = {}

export default Component

useState

useState 用于声明直接变量,指声明时不需要通过计算就能获得初始值的变量。useState 会返回两个值 getter & setter。

const [getter, setter] = useState('default value')

getter 是当前的变量值。

setter 是用于更新变量的函数,有两种用法。

  1. 不需要依赖 getter,直接传入新的变量值作为参数。
setter(newValue)
  1. 需要依赖 getter 做计算,参数为一个回调函数,参数为当前的变量值,返回新的变量值。
setter(getter => getter + 1)

Noted: getter 可以作为别的 Hooks 的依赖。

useEffect

useEffect 类似一个生命周期钩子,是 componentDidMountcomponentDidUpdatecomponentWillUnmount 的一个组合。常见用法有:

  1. 添加事件监听,并在组件销毁时移除监听。
// 每次窗口被缩放时打印窗口尺寸。
useEffect(() => {
  window.addEventListener('resize', () => {
    console.log(window.innerWidth, window.innerHeight)
  }, false)
}, [])
  1. 类似 Vue 的 watch 属性一样,监听某个变量的改变,当变量发生改变时触发别的逻辑。
// 每次姓名改变时输出全名。
const [firstName, setFirstName] = useState('Tony')
const [lastName, setLastName] = useState('Stark')

useEffect(() => {
  console.log(`My name is ${firstName} ${lastName}.`)
}, [firstName, lastName])

Noted: 使用 useEffect 时,一定要添加依赖(第二个参数)。除非你真的需要这个 useEffect 每次都被执行。

useMemo

useMemo 用于声明计算变量,计算变量指需要通过别的值计算获得值的变量。类似于 Vue 的计算属性 computed。

// 通过 useMemo 获得全名。

Noted: 和 useEffect 不同,useMemo 的第二个参数是必填的,如果不需要依赖任何变量,那么第二个参数为空数组 []。且 useMemo 可以作为别的 Hooks 的依赖。

useCallback

useCallback 顾名思义用于声明回调函数,如事件触发时的回调函数。

// 点击时打印一句话
const onClick = useCallback(() => {
  console.log('The element has been clicked.')
}, [])

<button type="button" onClick={onClick}>Button</button>
// 点击时打印全名
const [firstName, setFirstName] = useState('Tony')
const [lastName, setLastName] = useState('Stark')

const onClick = useCallback(() => {
  console.log(`My name is ${firstName} ${lastName}.`)
}, [firstName, lastName])

<button type="button" onClick={onClick}>Button</button>

Noted: 和 useMemo 一样,useCallback 的第二个参数也是必填的,如果不需要依赖任何变量,那么第二个参数为空数组 []。且 useCallback 可以作为别的 Hooks 的依赖。

除了回调函数,在实际开发的过程中还会有需要像工具函数的函数,建议把这些函数都单独封装,通过模块化的方式引用。不要在函数组件中定义功能性函数。