精读《setState 做了什么》

1 弁言

setState 是 React 框架最经常运用的敕令,它是用来更新状况的,这也是 React 框架划时代的功用。

然则 setState 函数是 react 包导出的,他们又是怎样与 react-dom react-native react-art 这些包连系的呢?

经由过程 how-does-setstate-know-what-to-do 这篇文章,能够解开这个隐秘。

2 概述

setState 函数是在 React.Component 组件中挪用的,所以最天然的遐想是,更新 DOM 的逻辑在 react 包中完成。

然则 react 却能够和 react-dom react-native react-art 这些包打合营,以至与 react-dom/server 合营在效劳端运转,那能够一定 react 包中不含有 DOM 更新逻辑。

所以能够揣摸,平台相干的 UI 更新逻辑散布在平台相干的包里,react 包只做了代办。

React 引擎不在 react 包里

从 react 0.14 版本以后,引擎代码就从 react 包中抽离了,react 包仅仅做通用接口笼统。

也就是说,react 包定义了范例的状况驱动模子的 API,而 react-dom react-native react-art 这些包是在各自平台的详细完成。

各平台详细的衬着引擎完成被称为 reconciler,经由过程这个链接能够看到 react-dom react-native react-art 这三个包的 reconciler 完成。

这说清楚明了 react 包仅通知你 React 具有哪些语法,而并不体贴怎样完成他们,所以我们须要连系 react 包与 react-xxx 一同运用。

关于 context,react 包仅仅会做以下定义:

// A bit simplified
function createContext(defaultValue) {
  let context = {
    _currentValue: defaultValue,
    Provider: null,
    Consumer: null
  };
  context.Provider = {
    $$typeof: Symbol.for("react.provider"),
    _context: context
  };
  context.Consumer = {
    $$typeof: Symbol.for("react.context"),
    _context: context
  };
  return context;
}

详细用到时,由 react-domreact-native 决议用何种体式格局完成 MyContext.Provider 这个 API。

这也说清楚明了,假如你差别步晋级 reactreact-dom 版本的话,就可能遇到如许的报错:fail saying these types are invalid,缘由是 API 定义与完成不婚配。

setState 怎样挪用平台完成

每一个平台对 UI 更新逻辑的完成,会封装在 updater 函数里,所以差别平台代码会为组件增加各自的 updater 完成:

// Inside React DOM
const inst = new YourComponent();
inst.props = props;
inst.updater = ReactDOMUpdater;

// Inside React DOM Server
const inst = new YourComponent();
inst.props = props;
inst.updater = ReactDOMServerUpdater;

// Inside React Native
const inst = new YourComponent();
inst.props = props;
inst.updater = ReactNativeUpdater;

差别于 props, updater 没法被直接挪用,因为这个 API 是由 react 引擎在 setState 时挪用的:

// A bit simplified
setState(partialState, callback) {
  // Use the `updater` field to talk back to the renderer!
  this.updater.enqueueSetState(this, partialState, callback);
}

关联能够这么形貌:react -> setState -> updater <- react-dom 等。

Hooks

Hooks 的道理与 setState 相似,当挪用 useStateuseEffect 时,其内部挪用以下:

// In React (simplified a bit)
const React = {
  // Real property is hidden a bit deeper, see if you can find it!
  __currentDispatcher: null,

  useState(initialState) {
    return React.__currentDispatcher.useState(initialState);
  },

  useEffect(initialState) {
    return React.__currentDispatcher.useEffect(initialState);
  }
  // ...
};

ReactDOM 供应了 __currentDispatcher(简化的说法):

// In React DOM
const prevDispatcher = React.__currentDispatcher;
React.__currentDispatcher = ReactDOMDispatcher;
let result;
try {
  result = YourComponent(props);
} finally {
  // Restore it back
  React.__currentDispatcher = prevDispatcher;
}

能够看到,Hooks 的道理与 setState 基础一致,但须要注重 reactreact-dom 之间传递了 dispatch,虽然你看不到。但这个 dispatch 必需对应到唯一的 React 实例,这就是为何 Hooks 不允许同时加载多个 React 实例的缘由。

updater 一样,dispatch 也能够被各平台完成重写,比方 react-debug-hooks 就重写了 dispatcher

因为须要同时完成 readContext, useCallback, useContext, useEffect, useImperativeMethods, useLayoutEffect, useMemo, useReducer, useRef, useState,工程量比较浩荡,发起相识基础架构就足够了,除非你要深切介入 React 生态建设。

3 精读

与其他 React 理会文章差别,本文并没有过于刨根题目的上来就理会 reconciler 完成,而是问了一个最基础的疑问:为何 setState 来自 react 包,但完成却在 react-dom 里?React 是怎样完成这个 magic 的?

经由过程这个疑问,我们相识了 React 更上层的笼统才能,怎样用一个包制订范例,用 N 包去完成它。

接口的气力

在一样平常编程中,接口也具有的壮大气力,下面举几个例子。

UI 组件跨三端的接口

因为 RN、Weex、Flux 的某些不足,越来越多的人挑选 “一个头脑三端完成” 的体式格局做跨三端的 UI 组件,如许既统筹了机能,又能够照顾到平台差异性,对差别平台组件细节做定制优化。

要实行这个计划,最大题目就是接口商定。一定要保证三套完成遵照一致套 API 接口,营业代码才能够完成 “针对恣意一个平台编写,自动移植到其他平台”。

比较经常运用的做法是,经由过程一套一致的 API 文件束缚,牢固组件的输入输出,差别平台的组件做平台详细完成。这个头脑和 React 千篇一律。

固然 RN 这些框架自身也是一致接口在差别平台完成的典范,只是做的不够完全,JS 与 Native 的通讯致使了机能不如源生。

通用数据查询效劳

通用数据查询效劳也比较盛行,经由过程磨平各数据库语法,让用户经由过程一套 SQL 查询各种类型数据库的数据。

这个计划中,一套通用的查询语法就相似 React 定义的 API,实行阶段会转化为各数据库平台的 SQL 方言。

小顺序融会计划

如今这类计划很火。经由过程基于 template 或许 jsx 的语法,一键宣布到各平台小顺序运用。

这类计划一定会笼一致套通用语法,以至险些等价与 reactreact-dom 的关联:一切相符范例的语法,转化为各小顺序平台的完成。

4 总结

这类分平台完成计划与跨平台计划照样有很大区分的,像 JAVA 虚拟机实质照样一套完成计划。而分平台的完成能够带来最原生的机能与体验,一样收到的束缚也最大,应当其 API 应当是一切平台支撑的一个子集。

别的,这类计划不仅能够用于 一套范例,差别平台的完成,以至能够用在 “一致平台的完成”。

无论是公司照样开源节界,都有很多反复的轮子或许平台,假如经由过程手艺委员会商定一套平台的完成范例,人人都遵照这个范例开辟平台,那未来就比较好做收敛,或许说收敛的第一步都是先一致 API 范例。

留下一个思考题:另有没有应用 setState 范例与完成星散的头脑案例?迎接留下你的答案。

议论地点是:
精读《setState 做了什么》 · Issue #122 · dt-fe/weekly

假如你想介入议论,请点击这里,每周都有新的主题,周末或周一宣布。前端精读 – 帮你挑选靠谱的内容。

    原文作者:黄子毅
    原文地址: https://segmentfault.com/a/1190000017787272
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞