React-hooks整理
当前React18.2版本,常用hooks功能和作用
基础hook
1.useState
作用:定义具有内部状态的数据,接收一个初始值,返回一个数组。
解决问题:解决函数组件无状态问题。解构出变量和响应式修改数据的唯一方法
import { useState } from "react";
const [count, setCount] = useState(10)
setCount(20);
<p>{count}</p>
2.useEffect
作用:1.数据监控,2.模拟生命周期
解决问题:解决函数无生命周期的问题
语法:语法 useEffect( callback, Array? )
- callback:业务逻辑函数。
- Array:一个数组
- 如果不存在:模拟componentDidUpdate,任何有状态的数据变化都会执行
- 如果为空数组:模拟componentDidMount,初始化完成之后执行
- 指定数据:数组内变量数据指针发生变化执行
- 模拟componentWillUnmount,callback的return 为一个函数,在销毁后执行
3.useContext
作用:数据共享(又称 “小状态机” ),必须在共同的祖先父级创建
解决问题:嵌套组件的值传递,兄弟组件间的数据,放置到共同的父级组件中
-
参数:必须是 context 对象本身。createContext 创建时赋值为默认值
-
通过 Provider 的value属性传递共享数据,value为当前值,覆盖默认值
// src/parent.jsx 父组件
import React,{createContext} from 'react';
const count = 1;
const count2 = 2;
export const CountContext = createContext(count);//一个context 对象,默认值是 count
<ThemeContext.Provider value={count2}>// 传递count2
<Counter />
</ThemeContext.Provider>
使用:
// src/child.jsx子组件
import React, { useContext } from "react";
import {CountContext} from './parent';// 写在一个模块中就不需要引入
const Counter = () => {
// 函数组件
const data = useContext(CountContext);
// 类组件中,使用如下申明,this.context 使用数据,
// static contextType = CountContext;
return (
<div>
<p>子组件获得的点击数量:{data}</p>
</div>
);
};
export default Counter;
注意:Context.Consumer
同样用于函数组件获取共享数据,用法复杂于useContext
#### 4.useReducer
作用:基本等同于一个局部的redux数据管理方式,返回一个数组
解决问题:解决逻辑较复杂且包含多个子值的数据修改,也可以使用useState
const [state, dispatch] = useReducer(reducer, initialState, init);
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
- state: 数据对象,
- dispatch: 接收一个具有type标识的对象,用于区分执行逻辑
- reducer: reducer(state, action){}函数,参数state: 将接收的数据,action:dispatch派发对象
- initialState: 初始数据
- init: 可选回调函数,惰性初始化,将参数二传入处理后,返回作为reducer数据。
5.useCallback
作用:根具依赖的数据缓存一个函数,使用时需要调用。
解决问题:解决页面加载时函数重新创建带来的性能问题。
语法:useCallback (callback, [ ])
- callback:缓存的函数
- 参数二:一个数组,数组中的任意一个变量或指针发生变化,都会创建一个新的函数
import { useCallback } from 'react'
const newUser2 = useCallback(()=>{
return user.name + "-----"
},[user])
<p>{newUser2()}</p>
6.useMemo
作用:计算属性,根据依赖的数据,返回一个新数据,赋给一个变量,具有缓存效果。
解决问题:解决页面每次加载组件内的数据都会重新赋值而带来的性能问题。
语法:useMemo(callback, [ ])
- callback:一个函数,必须有返回值,返回值作为变量的值
- 参数二:一个数组,数组中的任意一个变量或指针发生变化,都会执行callback函数,返回一个新的值,
import { useMemo } from "react";
const newUser = useMemo(()=>{
return user.name + "-----"
},[user])
<p>{newUser}</p>
useMemo和useCallback区别:
- useMemo返回的计算属性的结果,是一个变量
- useCallback返回的函数, 当你的变量没有发生变化的时候,返回的永远都是缓存的函数,
7.useRef
作用:获取节点,使用封装React.createRef。每次引用useRef,创建一个ref节点。
解决问题:current属性存储数据,current值发生变化不会重新渲染
import React,{useRef} from 'react'
export default function Sale() {
const pwdRef = useRef();
const getValue = () => {
console.log(Sale.inEle.value); // 间接绑定获取的是原生对象,直接value获取值
console.log(pwdRef.current); // 直接绑定的,current获取节点
}
return (
<div>
// 方式一
<input ref={params => Sale.inEle = params} type="text" />
// 方式二
<input ref={pwdRef} type="password" />
<button onClick={getValue}>获取文本框值</button>
</div>
)
}
8.useImperativeHandle
作用:减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法
解决问题:解决跨组件获取节点,useImperativeHandle
应当与 forwardRef(节点转发)
一起使用
语法:useImperativeHandle(ref, createHandle, [deps])
- ref:父组件传递的ref属性
- createHandle:返回一个对象, 以供给父组件中通过ref.current调用该对象中的方法,可以改写节点对象
- deps:描述对象
// 语法
// 下例中,父节点操作子节点
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
9.useLayoutEffect
作用:DOM结构更新后、渲染前执行,useLayoutEffect
内部更新计划将被同步刷新。可能会阻塞视觉更新。建议使用useEffect,useEffect的执行时机是浏览器完成渲染之后
解决问题:一定程度上解决防抖问题
10.useDebugValue
作用:定义在自定义hook内,用于在 React 开发者工具中显示自定义 hook 的标签。
解决问题:作为共享库的一部分,延迟格式化 debug 值,减少不必要的格式化处理
语法:useDebugValue(data, callback?)
- data:debug值(数据)
- callback:可选格式化函数,接受 debug 值作为参数,并且会返回一个格式化的显示值
useDebugValue(data, data => data.toDateString());
11.useDeferredValue
作用:延迟更新传递的值,在紧急地更新之后更新。
解决问题:React 将在其他工作完成后立即进行更新
const query = useSearchQuery('');
const deferredQuery = useDeferredValue(query);
// deferredQuery变化才更新,
12.useTransition
作用:创建一个事件执行过程中的动画,修改数据后,渲染之前执行动画。
解决问题:使用前,表现为延迟卡顿,使用后动画过渡来说明正在执行
语法:const [value, setValue] = useTransition(ms)
- ms:接受传入一个毫秒的参数用来修改最迟更新时间,
- 返回:
- value:boolean类型,过渡任务的等待状态pending,在执行过渡中为true
- setValue:启动该过渡任务的startTransition函数。
import React, { useState, useTransition } from 'react';
export default function Demo() {
const [value, setValue] = useState('');
const [searchQuery, setSearchQuery] = useState([]);
const [loading, startTransition] = useTransition(2000);
const handleChange = (e) => {
// 立即更新
setValue(e.target.value);
// 延迟更新
startTransition(() => {
setSearchQuery(Array(20000).fill(e.target.value));
});
};
return (
<div className="App">
<input value={value} onChange={handleChange} />
{loading ? (
<p>loading...</p>
) : (
searchQuery.map((item, index) => <p key={index}>{item}</p>)
)}
</div>
);
}
13.useId
作用:用于生成横跨服务端和客户端的稳定的唯一 ID 的同时避免 hydration 不匹配的 hook。
解决问题:用于生成横跨服务端和客户端的稳定的唯一 ID
- 无参数,返回string类型, useId调用一次视为一组,返回“:r+组索引:”
const id = useId();
console.log(typeof id , id);// string :r0:
<label htmlFor={id}>Do you like React?</label>
<input id={id} type="checkbox" name="react"/>
Library Hooks
Library Hooks 是为库作者提供的,用于将库深入集成到 React 模型中,通常不会在应用程序代码中使用。
14.useSyncExternalStore
作用:用于读取和订阅外部数据源的 hook,其方式与选择性的 hydration 和时间切片等并发渲染功能兼容。
解决问题:用于读取和订阅外部数据源的 hook
const state = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
- 参数:接受三个参数
subscribe
:用于注册一个回调函数,当存储值发生更改时被调用。getSnapshot
: 返回当前存储值的函数。getServerSnapshot
:返回服务端渲染期间使用的存储值的函数
- 返回state:存储的值
15.useInsertionEffect
作用:仅限于 css-in-js 库作者使用。在读取 useLayoutEffect
中的布局之前将样式注入 DOM。不能访问 refs,也不能安排更新。
解决问题:布局之前将样式注入 DOM,优先考虑使用 useEffect
或 useLayoutEffect
来替代。
useInsertionEffect(didUpdate);
React 中文网: https://react.docschina.org/docs/hooks-reference.html#library-hooks
React 文档: https://react.dev/reference/react