banner
banner
banner
NEWS LETTER

React-常用的HOOK

Scroll down

Hook 本质上就是一个函数,它简洁了组件,有自己的状态管理,生命周期管理,状态共享。
Hook API 索引

Hook 解决了:

  • 组件之间状态复用
  • 在函数组件中可以使用生命周期
  • 不区分组件时间使用场景

React 内置的 Hook

💚useState(状态管理)

  • 作用:为组件添加state,并通过setState来更新state,避免重复创建initialState
    1
    const [state, setState] = useState(initialState)
    • setState(设置变量)
    • useState(初始化变量)
  • 注意:setState()在React中『大部分是异步』,但也存在同步
    • 在setTimeout 回调函数中调用会『同步』修改
    • 在原生DOM事件的回调函数中调用会『同步』修改

💚useEffect(生命周期管理)

  • 作用:处理副作用(包括网络请求、直接操作DOM,使用计时器函数等),相当于compoentDidmount和compoentDidUpdate
    1
    2
    3
    4
    5
    6
    useEffect(() => {
    // 依赖项变化时执行的语句
    return () => {
    //(可选)清除useEffect,相当于compoentDidUnmount
    }
    }, [依赖项 || '为空则只执行一次'])

useLayoutEffect

  • 作用: 副作用会在 DOM 更新之后同步执行,会阻塞浏览器绘制
  • 语法: 与useEffect一样
  • 与useEffect区别:
    • useEffect 是『异步』执行,而useLayoutEffect是『同步』执行
    • useEffect是会在整个页面『渲染完』才会调用, 而 useLayoutEffect 是在浏览器重新『绘制屏幕之前』触发

💚useRef(获取 Dom 操作)

  • 作用:通过ref操作DOM,避免重复创建 ref 的内容
    1
    const ref = useRef(initialValue)
  • 使用:ref.current = 子组件的实例
  • 注意点:
    • 『改变 ref.current 属性时,React 不会重新渲染组件』,而useState会触发页面的重新渲染
    • 更新useRef是副作用,所以一般写在useEffect或事件处理函数里
    • 使用useRef来保存不影响组件视图输出信息 — 清除定时器
  • 使用场景: 用来获取上一次的值
    1
    2
    3
    4
    5
    6
    7
    const usePrevious = (value: string | number) => {
    const ref = useRef()
    useEffect(() => {
    ref.current = value
    })
    return ref.current
    }

useImperativeHandle(组件暴露值/方法)

  • 作用:向父组件暴露一个自定义的 ref(穿透ref),应当与forwardRef一起使用(包在forwardRef里面)
    1
    useImperativeHandle(ref,createHandle,dependencies)
    • ref:子组件向父组件暴露的实例
    • createHandle:函数,传递的父组件可操作的实例和方法
    • dependencies:监听状态,更新状态

💚useMemo(缓存值)

  • 作用:跳过不必要的计算和渲染性能的优化,缓存每次重新渲染都需要计算的结果
    1
    const newValue = useMemo(callback,[dependencies])
    • 只有依赖改变,才会重新执行
    • 返回值:初次渲染,返回不带参数调用的计算的结果,依赖不变,返回上次缓存的值,依赖变则返回新值

💚useCallback(缓存函数)

  • 概念:useMemo的语法糖,缓存的是一个函数,返回的也是一个函数
    1
    useCallback(fn,[dependencies])
  • 与useMemo的区别:
    • useCallback不会执行第一个参数函数,而是将『函数返回』
    • useMemo会执行第一个函数并且将『结果返回』

useReducer(redux 相似)

  • 作用:向组件添加一个管理状态的reducer,实现reducer函数,避免重新创建初始值
    1
    const [state, dispatch] = useReducer(reducer, initialArg, init?)
    • reducer:更新state的纯函数。参数为 state 和 action,返回值是更新后的state
    • initialArg:初始化state的任意值
    • init:计算初始值的函数。如果存在,使用init(initialArg)的执行结果作为初始值,否则使用initialArg
    • dispatch:更新 state 并触发组件的重新渲染
      • 用法:dispatch(newVar)

用于请求api,并处理数据的HOOK

参考 TanStack Query 中文文档

useInfiniteQuery

  • 作用:无限滚动翻页
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    const { 
    data, // 包含无限查询数据的对象,data.pages数组包含已获取的分页页面,data.pageParams数组包含用于获取分页页面的参数
    hasNextPage, // 含义:存在下一页 值:布尔值,如果getNextPageParam返回的不是undefined的,则为true
    hasPreviousPage, // 含义:存在上一页 值:布尔值,如果getPreviousPageParam返回的不是undefined的,则为true
    isFetchingNextPage, // 值:布尔值,区分后台刷新状态和加载更多状态
    isFetchingPreviousPage, // 值:布尔值,区分后台刷新状态和加载更多状态
    refetch
    } = useInfiniteQuery({
    queryKey: ["projects"], // 这里的key相当于useEffect的依赖,但是为了避免多个key都是同样的,最好在加个字符串,使queryKey唯一
    queryFn: fetchProjects, // async/await请求api的函数
    // 以下两个方法都是用于确定是否有更多数据要加载和或用来获取它所需的信息
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,
    });

useQuery/useQueries

  • 作用:获取请求接口的数据(并行请求)
    1
    2
    3
    4
    5
    6
    7
    const { data } = useQuery({
    queryKey: ['issues'],
    queryFn: 接口的函数,
    suspense: true, // 不需要处理加载或错误的状态
    enabled: false // 存在才会执行
    })
    useQueries([{queryKey:[],queryFn:Fn},{queryKey:[],queryFn:Fn}])

react-redux 的 hooks

  • 引入 import { hook } from ‘react-redux’

useSelector()

  • 从redux的store队形中提取数据(state)
    1
    const counter = useSelector( state => state.counter)

useDispatch()

  • 返回Redux store中对dispatch函数的引用, 即把dispatch方法暴露出来使用
    1
    2
    3
    4
    const dispatch = useDispatch()
    <button onClick={() => dispatch({ type: 'increment-counter'})}>
    julie
    </button>
  • 将dispatch传递给子组件,使用useCallback,然后暴露该组件给其它组件使用
    1
    2
    3
    4
    const incrementCounter = useCallback(()=> 
    dispatch({type: 'increment-counter'}
    ), [dispatch])
    <MyIncrementButton onIncrement={incrementCounter} />

useStore()

  • 返回redux Provider组件的store对象的引用
    1
    2
    3
    const store = useStore
    <div>{store.getStore}</div>
    // 但store中的state更新,这里不会自动跟新,所以适合存放不变的数据
其他文章
cover
React-如何封装HOOK
  • 24/11/01
  • 09:41
  • React
目录导航 置顶
  1. 1. Hook 解决了:
  2. 2. React 内置的 Hook
    1. 2.1. 💚useState(状态管理)
    2. 2.2. 💚useEffect(生命周期管理)
    3. 2.3. useLayoutEffect
    4. 2.4. 💚useRef(获取 Dom 操作)
    5. 2.5. useImperativeHandle(组件暴露值/方法)
    6. 2.6. 💚useMemo(缓存值)
    7. 2.7. 💚useCallback(缓存函数)
    8. 2.8. useReducer(redux 相似)
  3. 3. 用于请求api,并处理数据的HOOK
    1. 3.1. 参考 TanStack Query 中文文档
    2. 3.2. useInfiniteQuery
    3. 3.3. useQuery/useQueries
  4. 4. react-redux 的 hooks
    1. 4.1. useSelector()
    2. 4.2. useDispatch()
    3. 4.3. useStore()
请输入关键词进行搜索