Skip to content

useSate()

返回一个 state 和更新 state 的函数

  • 在初始渲染阶段,返回的 state 和传入 useState 的参数一致

  • 如果新的 state 需要通过前一次的 state 计算得出,那么可以将函数传递给 setState 函数

<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
  • 如果初始化 state 需要经过复杂的计算的出则可以使用惰性初始化
// bad
// 在组件每次渲染的时候都会执行此函数,但是只有在组件第一次初始化的时候使用
const count = someExpensiveComputation()
const [state, setState] = useState(count)

// good
const [state, setState] = useState(() => someExpensiveComputation())
  • 给 setState 函数传入相同的 state 不会导致组件的重新渲染。(React 使用 Object.is()来判断)

useEffect()

在组件渲染到页面能上后异步执行副作用函数

  • 清除副作用,如果不给 useEffect 函数传递第二个参数,它会在组件更新前清除副作用,然后在组件更新完成后在执行副作用
useEffect(() => {
  // 订阅
  const subscription = props.source.subscribe();
  return () => {
    // 清除订阅
    subscription.unsubscribe();
  };
});
  • 与 componentDidMount、componentDidUpdate 不同的是,在浏览器完成布局与绘制之后,传给 useEffect 的函数会延迟调用。

  • 给 useEffect 添加第二个参数指定依赖,在依赖发生变化的时候会执行

useLayoutEffect()

其函数签名与 useEffect 一致,但执行时机和 useEffect 不同。

  • 它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

  • 尽可能使用标准的 useEffect 以避免阻塞视觉更新。

  • useLayoutEffect 与 componentDidMount、componentDidUpdate 的调用阶段是一样的。

useMemo()

返回一个记忆的值(memoized value )。把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。

useCallback()

返回一个 memoized 回调函数。把内联回调函数及依赖项数组作为参数传入 useCallback,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。

  • useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

useRef()

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref 对象在组件的整个生命周期内保持不变。

  • 用于获取 DOM 节点
export function TextInputWithFocusButton() {
  const inputEl = useRef()
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    console.log(inputEl.current)
    inputEl.current.focus()
  }
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  )
}
  • 获取上一次渲染的 state
export function PrevState() {
  const [count, setCount] = useState(0)
  const prevCount = useRef(null)

  useEffect(() => {
    prevCount.current = count
  }, [count])

  return (
    <div>
      <button onClick={() => setCount((count) => count + 1)}>Click {count}</button>
      <p>Prev Count: {prevCount.current}</p>
      <p>Current Count: {count}</p>
    </div>
  )
}
  • 保存句柄
export function ClearInterval() {
  const [count, setCount] = useState(0)
  const it = useRef()

  useEffect(() => {
    it.current = setInterval(() => {
      setCount((count) => count + 1)
    }, 1000)
  }, [])

  useEffect(() => {
    if (count > 10) {
      clearInterval(it.current)
    }
  }, [count])

  return <p>{count}</p>
}