React常用hooks快速梳理

116 阅读5分钟

react hooks.png

本文旨在为大家快速梳理React常用Hooks的作用和用法。目前只更新了useState,useEffect,useMemo,useCallback,useRef,useContext后面还会更新其他几个。如有不甚详尽之处请各位大佬多多指出。

useState

说明: useState可以让你在函数组件中进行状态管理
用法:

const [state, setState] = useState(initialState);

注意:\

  1. 这里是通过数组解构的方式来定义状态名并且获取useState()的返回值,例如[something, setSomething]。useState()有2个返回值,第一个数组元素是用来读取state的值(但它是只读的),我们要通过第二个数组元素setSomething来设置它的值。\
  2. state中不要保存可以通过计算得到的值。比如props,cookie/localStorage, url的值。
  3. useState(initialState)这里的initialState可以传一个值,也可以传一个函数,这个函数返回一个值当做初始状态,并且这个函数只会在初始渲染时执行一次;
  4. 使用setState(),修改值时是异步更新
  5. 多次调用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.使用对象或数组作为依赖项时,需要注意浅比较的问题,可以使用useRefuseMemouseCallback等钩子来解决这个问题。以下是使用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 在其父组件的路径上。

like.png

参考来源
React官方文档: react.dev/reference/r…