# 1.React Hook

  • Hook 分类

  • 除了 useRef,其他都可以归类为 自变量/因变量

# 自变量

  • useState
  • useReducer
  • useContext

# useState

  // 1 定义x的方法,并且初始值为 0
  const [x,setX] = useState(0);

  // 3 定义改变x的方法,每次调用时 都会让x的只+1
  const changeX = () => setX(x + 1);

  // 2 接着定义组件所描述的字符,并将x的值 渲染为li 标签的值
  // 4 将changex 绑定为ul的回调函数,点击视图触发更新; x 变化 => 视图变化
	<ul onClick={changeX}>
    <li>x是{x}</li>
  </ul>
1
2
3
4
5
6
7
8
9
10
11

描述一下函数组件.useState 定义了 x,x 的变化导致 li 的变化,所以 useState 是自变量,导致了 li 的变化=> 对应了视图变化;

# 组件的功能不仅描述视图,还能产生副作用 - useEffect

const [x, setX] = useState(0);

const changeX = () => setX(x + 1);

// 调用useEffect,依赖于x,当x 变化时,将title 赋值为x
useEffect(() => {
  document.title = x;
}, [x]);
// 第一个参数是函数,异步操作。
// 第二个参数是数组,代表依赖项,依赖项变化则执行第一个函数。
// 数组可以省略,省略则在每一次组件渲染都会执行一次。
1
2
3
4
5
6
7
8
9
10
11

# 进阶: 从 useState 到 useReducer

  • useReducer 解决的问题:假设有数据 a,要进行传递。只有一级层次的情况下可以通过 props 传递,但是如果有 n 级组件,那么一级传到 n 级会很麻烦。
  • 如何解决:在一级组件通过 createContext 后,在后续组件需要用到地方通过 useContext 可以直接消费一级组件的 context。

# 因变量

  • useMemo
  • useEffect
  • useCallback

# 可以缓存的 useMemo 和 useCallback

  1. 可以用 useMemo 和 useCallback 分别包裹 y 和 cahngeX
  • useMemo 用来缓存一个因变量,需要显式的指定因变量依赖的自变量
  • useCallback 缓存一个函数类型的因变量,也需要显式的指定依赖的自变量
const [x, setX] = useState(0);

const y = useMemo(() => 2 * x + 1, [x]); // 需要显式的指定y依赖于x的变化
// useCallback 缓存一个函数类型的因变量
const changX = useCallback(() => setX(x + 1), [x]);
1
2
3
4
5
  • 可以看到使用 useMemo 和 useCallback 也是一样的;
    1. 使用 hooks 显式指明因变量
    2. 使用的时候 y 和 changeX 会被缓存下来,只要 x 不变,始终读取的是缓存的值
    3. 不使用的时候,每次函数组件调用,都会创建新的 y 和 changeX
    4. 在遇到性能瓶颈之前,都可以不使用这 2 个 hooks

# useMemo和useCallback的区别

  • useMemo 经常与 useCallback 一同出现。当尝试优化子组件时,它们都很有用。他们会 记住(或者说,缓存)正在传递的东西:
import { useMemo, useCallback } from 'react';

function ProductPage({ productId, referrer }) {
  const product = useData('/product/' + productId);

  const requirements = useMemo(() => { //调用函数并缓存结果
    return computeRequirements(product);
  }, [product]);

  const handleSubmit = useCallback((orderDetails) => { // 缓存函数本身
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }, [productId, referrer]);

  return (
    <div className={theme}>
      <ShippingForm requirements={requirements} onSubmit={handleSubmit} />
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

区别在于你需要缓存 什么:

  • useMemo 缓存函数调用的结果。在这里,它缓存了调用 computeRequirements(product) 的结果。除非 product 发生改变,否则它将不会发生变化。这让你向下传递 requirements 时而无需不必要地重新渲染 ShippingForm。必要时,React 将会调用传入的函数重新计算结果。

  • useCallback 缓存函数本身。不像 useMemo,它不会调用你传入的函数。相反,它缓存此函数。从而除非 productId 或 referrer 发生改变,handleSubmit 自己将不会发生改变。这让你向下传递 handleSubmit 函数而无需不必要地重新渲染 ShippingForm。直至用户提交表单,你的代码都将不会运行。

  • 如果你已经熟悉了 useMemo,你可能发现将 useCallback 视为以下内容会很有帮助:

// 在 React 内部的简化实现
function useCallback(fn, dependencies) {
  return useMemo(() => fn, dependencies);
}
1
2
3
4

# useTransition

Last Updated: 6/3/2024, 1:08:34 AM