React Hooks 使用指南

Hook 是 React 16.8 开始支持的新特性,旨在用函数式组件代替类式组件。本文记录常用Hook用法及注意点

1、useState

返回一个 state,以及更新 state 的函数。给函数式组件增加内部状态,状态一旦变化,组件会重新渲染

const [state, setState] = useState(initialState);
  • useState 可以接受单值或函数,若是函数,则以函数返回值作为初始state,且该函数仅在初始化时执行一次,后期组件更新不再执行
  • setState 可以接受单值或函数,若是函数,则函数第一个参数是上一个state值,返回值若与上一个state值一样,则组件不重新渲染
  • 与类式组件的setState不同,函数组件的 setState 不会合并所有状态,不过可以这样做到:
setState(prevState => {
  // 也可以使用 Object.assign
  return {...prevState, ...updatedValues};
});
  • 使用 Object.is方法判断前后 state 是否相等

2、useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

当传入第三个函数参数,则state=init(initialArg);否则 state = initialArg

  • useReducer 是 useState 的替代方案
  • reducer: (state, action) => newState
const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

3、useEffect

接收一个包含命令式、且可能有副作用代码的函数A和一个依赖数组B作为参数。函数A会在组件渲染到屏幕之后执行。每次重新渲染组件时,B中的值不变化,则函数A不会重新执行

useEffect(()=>{
    // 副作用代码,如订阅、dom操作、定时器、获取数据等
},[]);
  • 函数A可以返回一个函数,用于清除副作用,如取消订阅、定时器等操作
  • 如果组件多次渲染(通常如此),则在执行下一个 effect 之前,上一个 effect 就已被清除
  • 函数A会在浏览器绘制后延迟执行,但会保证在任何新的渲染前执行。因此不应在函数A中执行阻塞浏览器更新屏幕的操作,不然用户会感觉到视觉上的不一致

4、useLayoutEffect

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

  • useEffect 是异步的,useLayoutEffect 是同步的

5、useCallback

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback 返回第一个函数A参数的记忆化版本,该函数A的引用只有在依赖数组的元素发生改变时才会改变。useCallback本身会在每次重新渲染时执行

6、useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

返回一个记忆化的值V,该值只有在依赖数组的元素发生改变时才会改变。useCallback本身会在每次重新渲染时执行。

  • useCallBack 用于记忆函数,useMemo 用于记忆需要复杂计算而来的衍生值
  • useMemo 的第一个函数参数在初次渲染时也会执行

7、useRef

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。

// const refContainer = useRef(initialValue);
function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
  • ref 对象的 current 属性值是可变的,可保存任何值
  • ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。
  • 回调 ref
function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    <>
      <h1 ref={measuredRef}>Hello, world</h1>
      <h2>The above header is {Math.round(height)}px tall</h2>
    </>
  );
}

8、自定义 Hook

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}
  • 用 useXXX 命名
  • 通常内部调用 useState,useEffect 等内置hook
  • 返回值随意
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 在学会使用React Hooks之前,可以先看一下相关原理学习React Hooks 前言 在 React 的世界...
    DC_er阅读 9,200评论 1 16
  • Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他...
    孤独的小色狼阅读 418评论 0 0
  • 什么是 Hooks 以往,React 组件都是通过 class 的形式来编写,只有无状态组件才可以用函数来编写。H...
    Actoress阅读 1,175评论 0 0
  • 前言 自react16.8发布了正式版hook用法以来,我们公司组件的写法逐渐由class向函数式组件+hook的...
    大春春阅读 4,276评论 3 7
  • Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他...
    Oldboyyyy阅读 4,938评论 0 3

友情链接更多精彩内容