React Hook

133 阅读5分钟

useState

定义变量

const [state, setState] = useState(initialState);
  • state:UI的数据源
  • setState:改变 state 的函数
  • initialState:初始默认值

useEffect

副作用(Side Effect:是指 function 做了和本身运算返回值无关的事,如请求数据、修改全局变量,打印、数据获取、设置订阅以及手动更改 React 组件中的 DOM 都属于副作用

useEffect(() => {
    // 挂载
    return () => {
      // 卸载
    }
}, [])

通常我们用于监听addEventListenerremoveEventListener

useEffect(() => {
   // 依赖值得变化
}, [count])

useContent

上下文,设置全局共享数据,使所有组件可跨层级实现共享。

useContent的参数一般是由createContext的创建,通过 CountContext.Provider 包裹的组件,才能通过 useContext 获取对应的值。

const TestContext = createContext({})

<TestContext.Provider value={value}>
  <Child />
</TestContext.Provider> 

const Child = () => {
  const value = useContext(TestContext)
  
  console.log(value)
  return null;
}

useReducer

它类似于redux功能的api

const [state, dispatch] = useReducer(reducer, initialArg, init);
  • state:更新后的state
  • dispatch:可以理解为和useStatesetState一样的效果
  • reducer:可以理解为reduxreducer
  • initialArg:初始值
  • init:惰性初始化
const Component = () => {

  const [count, dispatch] = useReducer((state, action)=> {
    switch(action?.type){
      case 'name':
        return action?.payload;
      default:
        return state;
    }
  }, '小张');

  return <div style={{padding: 20}}>
    <div>who? {name}</div>
     
    <Button onClick={() => dispatch({type: 'name', payload: '小王' })} >
      小王
    </Button>
  </div>
}

useMemo

useMemo:与memo差不多,都是判断是否满足当前的限定条件来决定是否执行callback函数,而useMemo的第二个参数是一个数组,通过这个数组来判定是否更新回掉函数。

当一个页面内容非常复杂,模块非常多的时候,函数式组件会从头更新到尾,只要一处改变,所有的模块都会进行刷新,这种情况显然是没有必要的。

理想的状态是各个模块只进行自己的更新,不要相互去影响。

const Index = (list: number[]) => {
  return useMemo(() => {
    // 父组件的其他更新不会更新子组件
  }), []) 
}

useCallback

useCallbackuseMemo极其类似,可以说是一模一样,唯一不同的是useMemo返回的是函数运行的结果,而useCallback返回的是函数

这个函数是父组件传递子组件的一个函数,防止做无关的刷新,其次,这个组件必须配合memo,否则不但不会提升性能,还有可能降低性能

React.memo会通过浅比较里面的props,如果没有memo,那么使用的useCallback也就毫无意义

因为useCallback本身是需要开销的,所以反而会增加性能的消耗。

useRef

可以获取当前元素的所有属性,并且返回一个可变的ref对象,并且这个对象只有current属性

const refContainer = useRef(initialValue);

可以缓存数据,减少了不必要的更新,如过采取useState则会重新渲染。

useImperativeHandle

使用 ref 时自定义暴露给父组件的实例值

有的时候我们需要在最外层的组件上控制其他组件的方法,希望最外层的点击事件,同时执行子组件的事件

useImperativeHandle(ref, createHandle, [deps])
  • refuseRef所创建的ref
  • createHandle:处理的函数,返回值作为暴露给父组件的 ref 对象。
  • deps:依赖项,依赖项更改形成新的 ref 对象。

useLayoutEffect

要注意的是useLayoutEffect在 DOM 更新之后,浏览器绘制之前,这样做的好处是可以更加方便的修改 DOM,获取 DOM 信息,这样浏览器只会绘制一次,所以useLayoutEffectuseEffect之前执行

如果是useEffect的话 ,useEffect 执行在浏览器绘制视图之后,如果在此时改变DOM,有可能会导致浏览器再次回流重绘

除此之外useLayoutEffect的 callback 中代码执行会阻塞浏览器绘制

useDebugValue

可用于在 React 开发者工具中显示自定义 hook 的标签

useSyncExternalStore

是一个推荐用于读取订阅外部数据源的 hook,其方式与选择性的 hydration 和时间切片等并发渲染功能兼容

const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot])
  • subscribe: 订阅函数,用于注册一个回调函数,当存储值发生更改时被调用。此外, useSyncExternalStore 会通过带有记忆性的 getSnapshot 来判别数据是否发生变化,如果发生变化,那么会强制更新数据。
  • getSnapshot: 返回当前存储值的函数。必须返回缓存的值。如果 getSnapshot 连续多次调用,则必须返回相同的确切值,除非中间有存储值更新。
  • getServerSnapshot:返回服务端(hydration模式下)渲染期间使用的存储值的函数

useTransition

返回一个状态值表示过渡任务的等待状态,以及一个启动该过渡任务的函数。

const [isPending, startTransition] = useTransition();
  • isPending:过渡状态的标志,为true时是等待状态
  • startTransition:可以将里面的任务变成过渡任务

useDeferredValue

接受一个值,并返回该值的新副本,该副本将推迟到更紧急地更新之后。

如果当前渲染是一个紧急更新的结果,比如用户输入,React 将返回之前的值,然后在紧急渲染完成后渲染新的值。

也就是说useDeferredValue可以让状态滞后派生

const deferredValue = useDeferredValue(value);
  • value:可变的值,如useState创建的值
  • deferredValue: 延时状态

useTransitionuseDeferredValue对比

  • 相同点:useDeferredValueuseTransition一样,都是过渡更新任务
  • 不同点:useTransition给的是一个状态,而useDeferredValue给的是一个值

useInsertionEffect

与 useEffect一样,但它在所有 DOM 突变 之前同步触发。

在执行顺序上 useInsertionEffect > useLayoutEffect > useEffect

seInsertionEffect 应仅限于 css-in-js 库作者使用。优先考虑使用 useEffect 或 useLayoutEffect 来替代。

useId

useId : 是一个用于生成横跨服务端和客户端的稳定的唯一 ID 的同时避免hydration 不匹配的 hook