当前位置: 首页 > news >正文

React Hooks: useRef,useCallback,useMemo用法详解

 

1. useRef(保存引用值)

useRef 通常用于保存“不会参与 UI 渲染,但生命周期要长”的对象引用,比如获取 DOM、保存定时器 ID、WebSocket等。

新建useRef.js组件,写入代码:

import React, { useRef, useState } from 'react'

export default function UseRef() {

    const name = useRef<HTMLInputElement>(null)
    let [list, setList] = useState(['000', '111', '222'])

    let btnHandle = () => {
        if (name.current) {
            setList([...list, name.current.value])
            name.current.value = ''
        }
    }

    let delHandle = (index: number) => {
        let temList = [...list]
        temList.splice(index, 1)
        setList(temList)
    }

    return (
        <div>
            <input ref={name} />
            <button onClick={btnHandle}>click</button>
            <ul>
                {list.map((value, index) => {
                    return (
                        <li key={index}>
                            {value}
                            <button onClick={() => delHandle(index)}>删除</button>
                        </li>
                    )
                })}
            </ul>
        </div>
    )
}

上面的name会保存引用值,可以带入到点击事件,效果: 

不仅如此,useRef还能在函数组件中保持状态:

import React, { useState, useRef } from 'react'

export default function UseRef() {

    const [count, setCount] = useState(0)

    let myCount = useRef(0)

    const addHandle = () => {
        setCount(count + 1)
        myCount.current++
    }

    return (
        <div>
            <button onClick={addHandle}>click</button>
            {count} - {myCount.current}
        </div>
    )
}

上面的myCount当值变化时,能够实时保存。

2. useCallback(记忆函数)

防止因为组件重新渲染,导致方法被重新创建,起到缓存作用,只有第二个参数变化了,才重新声明一次。

新建 UseCallback.js方法组件,写入代码:

import React, { useCallback, useEffect } from 'react'

export default function UseCallback() {

    const [userId, setUserId] = useState(1)
    const [user, setUser] = useState<any>(null)
    const [counter, setCounter] = useState(0)

  const fetchUser = useCallback(() => {
    console.log(`Fetching user with ID ${userId}...`)
    fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
      .then(res => res.json())
      .then(data => setUser(data))
  }, [userId])

  useEffect(() => {
    fetchUser()
  }, [fetchUser])

    return (
        <div>
            <h2>用户信息</h2>
            {user ? (
                <div>
                    <p>名字: {user.name}</p>
                    <p>邮箱: {user.email}</p>
                </div>
            ) : (
                <p>加载中...</p>
            )}
            <button onClick={() => setUserId(id => id + 1)}>切换用户</button>
            <button onClick={() => setCounter(c => c + 1)}>其他按钮(不影响 fetch)</button>
            <p>Counter: {counter}</p>
        </div>
    )
}

export default UseCallback

上面仅当 userId 变化时,fetchUser 函数才会变化,userId 不变就不重新生成函数。效果: 

如果不使用 useCallback,每次渲染时函数都会创建,这在传给子组件或放到 useEffect / onClick 等地方时,会带来性能浪费、重复渲染、无法复用的问题。

3. useMemo(记忆组件)

useMemo 是 值级缓存,用于缓存变量、数组、对象、计算结果,不同于 useCallback 是 函数级缓存。

import React, { useState, useMemo } from 'react'

const UserList = () => {
  const [query, setQuery] = useState('')
  const [users] = useState([
    'Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'George'
  ])

  const filteredUsers = useMemo(() => {
    console.log('Filtering...')
    return users.filter(user => user.toLowerCase().includes(query.toLowerCase()))
  }, [query, users])

  return (
    <div>
      <input
        placeholder="搜索用户"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      <ul>
        {filteredUsers.map((user, index) => (
          <li key={index}>{user}</li>
        ))}
      </ul>
    </div>
  )
}

export default UserList

结果:

 上面只有当 query 或 users 变化时,才重新过滤;如果不使用 useMemo,每次组件渲染时,users.filter(...) 都会执行一次,即使输入没有变。

http://www.dtcms.com/a/129307.html

相关文章:

  • Python中内置的数据结构类型详析(内置数据容器)
  • 【Java集合】HashSet源码深度分析
  • [python]从whl文件名认识支持python版本和操作系统
  • 第二十二: go与k8s、docker相关编写dockerfile
  • 策略模式实现 Bean 注入时怎么知道具体注入的是哪个 Bean?
  • Java中的static都能用来修饰什么?
  • 【强化学习-蘑菇书-2】通过具体的例子来学习如何与 Gym 库进行交互——小车上山(MountainCar-v0)
  • idea开发工具多账号使用拉取代码报错问题
  • 探秘 HTML5 Geolocation:精准定位用户位置,拓展网页交互边界
  • Redis-数据类型
  • AF3 ProteinDataset类的get_anchor_ind方法解读
  • 基于生成对抗网络(GAN)的手写数字生成实践
  • 了解SpringAOP
  • 【React】React-toolkit
  • java设计模式-组合模式
  • 路由交换网络专题 | 第二章 | RIP | OSPF | 路由聚合 | 路由过滤 | 静默接口
  • Linux上位机开发实践(底板设计)
  • matlab与dsp28335联调
  • MySQL索引介绍
  • 什么是VLA
  • 【数据结构】HashMap源码 —— 简单介绍
  • 人工智能之数学基础:奇异值分解SVD
  • JAVA SDK通过proxy对接google: GCS/FCM
  • 实测解析:FP7208 在汽车照明、摄影照明、教育照明以及太阳能照明等不同市场领域的典型应用参数解析和案例分析
  • Kingbase 常用运维命令总结
  • Vue的学习总结-day02
  • Pinyin4j修仙指南:从汉字到拼音的声韵转换大法
  • 部署Fish-Speech实现声音克隆及文本转语音
  • Windows 系统中安装 Git 并配置 GitHub 账户
  • C++基本语法