本文旨在为大家快速梳理React常用Hooks的作用和用法。目前只更新了useState,useEffect,useMemo,useCallback,useRef,useContext后面还会更新其他几个。如有不甚详尽之处请各位大佬多多指出。
useState
说明: useState可以让你在函数组件中进行状态管理
用法:
const [state, setState] = useState(initialState);
注意:\
- 这里是通过数组解构的方式来定义状态名并且获取useState()的返回值,例如
[something, setSomething]。useState()有2个返回值,第一个数组元素是用来读取state的值(但它是只读的),我们要通过第二个数组元素setSomething来设置它的值。\ - state中不要保存可以通过计算得到的值。比如props,cookie/localStorage, url的值。
useState(initialState)这里的initialState可以传一个值,也可以传一个函数,这个函数返回一个值当做初始状态,并且这个函数只会在初始渲染时执行一次;- 使用setState(),修改值时是异步更新的
- 多次调用setState(),执行更新频率; 传入普通值,只会执行最后一次更新;传入函数,每次都会执行
const [age,setAge] = useState(0);
const handleAdd = () =>{
setAge(age+1);
setAge(age+1);
// 传入普通值,只会执行最后一次更新
}
const handleAdd = () =>{
setAge(age => age+1);
setAge(age => age+1);
// 传入函数,每次都会执行
}
useEffect
说明:useEffect可以在组件render完成后执行一些副作用操作(如获取数据、更新DOM或订阅事件等)
一般用法:
useEffect(setup, dependencies?)
// 这里setup是一个回调函数,用于执行副作用操作。当组件挂载到DOM树上时,useEffect函数会调用这个回调函数。
// dependencies是依赖项,当这些依赖项发生变化时,useEffect函数会重新运行。
特殊用法:
1.没有依赖项,则每次 render 后都会重新执行(可能会导致性能问题或不必要的副作用)。
2.空数组作为依赖项,则setup只在组件首次render和卸载时运行一次。
首次render运行
useEffect(() => {}, [])
卸载时运行
useEffect() => {
return () => {
//这里写需要组件销毁时执行的操作...
}
}, [])
注意:
1.依赖项参数必须传一个数组。
2.使用对象或数组作为依赖项时,需要注意浅比较的问题,可以使用useRef、useMemo或useCallback等钩子来解决这个问题。以下是使用useRef的例子:
const objectRef = useRef({ prop: "value" });
const arrayRef = useRef([1, 2, 3]);
useEffect(() => {
// 使用objectRef.current和arrayRef.current进行操作
}, [objectRef.current, arrayRef.current]);
useCallback
说明:useCallback可以让你在组件重新渲染时缓存一个函数的定义。使用useCallback可以避免在每次重新渲染组件时都创建一个新的函数。
用法:
const cachedFn = useCallback(fn, dependencies)
// 这里 fn 是定义的回调函数,dependencies 是依赖的变量数组。只有当某个依赖变量发生变化时,才会重新声明 fn 这个回调函数。
小demo示例:
假设你有一个组件,在其中需要使用一个回调函数作为props传递给子组件。如果你每次重新渲染组件时都创建一个新的回调函数,子组件可能会在每次重新渲染时都重新渲染,即使传递给它的props没有变化。这可能会导致性能问题。
const MyComponent = () => {
const [count, setCount] = useState(0);
// 使用useCallback可以避免这个问题。你可以将要传递给子组件的回调函数作为useCallback的第一个参数,并将回调函数中所依赖的变量数组作为第二个参数。这样,useCallback会缓存这个回调函数的引用,并在组件重新渲染时检查依赖项是否发生变化。如果依赖项没有变化,useCallback会返回之前缓存的函数引用,否则会重新计算函数并返回一个新的函数引用。
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
<ChildComponent onClick={handleClick} />
</div>
);
};
useMemo
说明:useMemo可以让你在组件重新渲染时缓存一个计算的结果,可以避免在每次重新渲染组件时都重新计算相同的值。
用法:
const cachedValue = useMemo(calculateValue, dependencies)
注意:
useMemo的第一个参数是一个计算函数,用于计算要缓存的值。useMemo函数会返回一个缓存的值。当组件重新渲染时,useMemo会检查值的依赖项是否发生了变化。如果依赖项没有变化,useMemo会返回之前缓存的值,否则会重新计算值并返回一个新的值。
useRef
说明:useRef允许你创建一个可变的引用,该引用在渲染之间保持不变。
功能1:获取DOM节点、保存DOM节点的引用。
功能2:储存跨渲染数据。(我们可以把 useRef 看作是在函数组件之外创建的一个容器空间。在这个容器上,我们可以通过唯一的 current 属设置一个值,从而在函数组件的多次渲染之间共享这个值的能力。)
用法:
const someRef = useRef(initialValue)
//someRef.current 获取DOM节点
useContext
说明:useContext可以从组件中读取和订阅上下文信息。
用法:
const value = useContext(SomeContext)
另外我还写了一个小demo,有兴趣的可以移步看看 十分钟使用useContext实现简单的多语言切换
注意:
你或许已经发现,Context 相当于提供了一个定义 React 世界中全局变量的机制,而全局变量则意味着两点:
1.会让调试变得困难,因为很难跟踪某个 Context 的变化究竟是如何产生的。
2.让组件的复用变得困难,因为一个组件如果使用了某个 Context,它就必须确保被用到的地方一定有这个 Context 的 Provider 在其父组件的路径上。
参考来源
React官方文档: react.dev/reference/r…