useState 和它的朋友们

·  阅读 1856

你知道事实上 useState 和 useReducer 在 React 源码中是同一个方法吗?

固然, React 为你提供了单独的调用 useState 或 useReducer 的接口方法:

// source: https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js
export function useState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}

export function useReducer<S, I, A>(
  reducer: (S, A) => S,
  initialArg: I,
  init?: I => S,
): [S, Dispatch<A>] {
  const dispatcher = resolveDispatcher();
  return dispatcher.useReducer(reducer, initialArg, init);
}
复制代码

然而 React 内部在 mount 和 update 过程中, 调用的实际上是同一个方法:

// source: https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.new.js
function updateState<S>(
  initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
  // `updateState` 调用的实际上是传入了默认 `basicStateReducer` 方法的 `updateReducer` 
  return updateReducer(basicStateReducer, (initialState: any));
}

//这里就是默认的 reducer 方法:
function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
  return typeof action === 'function' ? action(state) : action;
}
复制代码

因此,你完全可以通过 useState 自己实现一个 useReducer hook:

import { useState } from 'react'

// 你只需传入 `reducer` 参数,替换掉 `basicStateReducer` 方法即可:
export function useReducer(reducer, initialState) {
    const [state, setState] = useState(initialState)

    const dispatch = (action) => {
        setState(prevState => reducer(prevState, action))
    }

    return [state, dispatch]
}
复制代码

除此之外,我们甚至可以用 useState 来实现 useRef hook:

export function useRef(initialValue) {
  // 你可以把 `ref` 当作不更新的 `state` 来看待
  const [ref, unused] = useState({ current: initialValue });
  return ref;
}
复制代码

在我们使用 React 进行编程时, useRef 这类 hook 被称为 逃生舱(Escape Hatches)useEffect 也属于此类 , 因为它可以让你跳脱到 React 自动渲染更新的逻辑之外运行 DOM 操作等一系列所谓 “副作用” 的代码。

假如你从不使用 setState 方法来更新某个 state,这个对象内部的信息就可以在 React 的多次渲染中得以保存,这样的 state 就可以起到与 ref 相同的作用。

事实上,上述的两个用 useState 实现 useReduceruseRef 的示例都是出现在 Reactbeta 文档 当中的。

beta 版文档的整体架构已经编写完成,阅读体验相较于旧版文档也更加丝滑,概念由浅入深,每章节末尾还附送在线习题,整体感觉和 Vue 的新版文档不分伯仲:

截屏2022-08-13 20.06.43.png

截屏2022-08-13 20.06.59.png

(总感觉前端就和 counter todo 之类的例子过不去了...)

你也可以暂时在 beta react 中文文档 阅读,当然目前还没有完整翻译。

最后也希望有能力的同学一起参与到 react 中文文档 的翻译工作中来,做一点微小的贡献~

分类:
前端
收藏成功!
已添加到「」, 点击更改