来自 stackoverflow 提问 How to detect a React component vs. a React element? (opens new window)
React 组件我是知道的 class、function 声明的两种
React 元素听过,到底是什么啥玩意
# Reat 元素
先说下 JSX,Javascript 的扩展语法
React 开发通常在 .jsx 或 .tsx
结尾文件中写 JSX 代码的
它到底是什么?它就是下面这个玩意,需要 Babel 转码才能正常使用
// 这就是 JSX,请结合 Babel 测试
const ele = <div>我是 JSX</div>
console.log(typeof ele) // object
2
3
4
看着像 HTML 标签元素一样,其他它是一个对象
所以 JSX 是一个像 HTML 标签元素的对象
没错,这就是 React 元素 (opens new window)
React 元素本质是调用 React.createELement
方法返回的对象
记住,只要最终通过 React.createElement 方法返回的对象都是 React 元素
# 判断 React 元素
通过 React.isValidElement
判断
本质是判断 React 元素对象上的 $$typeof 属性
React 元素结构,直观感受下
# 创建 React 元素的几种方式
class Foo extends React.Component {
render(){
return <h1>Hello</h1>;
}
}
function Bar() {
return <p>323</p>
}
let ele = <h3>323</h3>
let foo = <Foo />
let bar = <Bar />
// 具体看 Babel 转换后的
class Foo extends React.Component {
render() {
return /*#__PURE__*/ React.createElement("h1", null, "Hello");
}
}
function Bar() {
return /*#__PURE__*/ React.createElement("p", null, "323");
}
// 下面都是 React 元素,通过调用 React.createElement 返回的对象
let ele = /*#__PURE__*/ React.createElement("h3", null, "323");
let foo = /*#__PURE__*/ React.createElement(Foo, null);
let bar = /*#__PURE__*/ React.createElement(Bar, null);
// 结果很明显的
React.isValidElement(ele) // true
React.isValidElement(foo) // true
React.isValidElement(bar) // true
// 其实下面的也是 React 元素
let bar1 = Bar()
React.isValidElement(bar1) // true
// 但下面的不是
let foo1 = new Foo() // foo1 不是 React 元素
React.isValidElement(foo1) // false
// 但通过 render 方法返回的就是
let foo2 = Foo.prototype.render()
React.isValidElement(foo2) // true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# React 元素分类
分为 DOM 类型与 class 或 function 创建的自定义合成类型
通过 React 元素对象 type 属性判断
字符串是 DOM 类型, function 为合成类型
通过上面 React 元素结构图很直观的看到
// DOM 类型 React 元素
function isDOMTypeElement(element) {
return React.isValidElement(element) && typeof element.type === 'string'
}
// 自定义合成类型的 React 元素
function isCompositeTypeElement(element) {
return React.isValidElement(element) && typeof element.type === 'function'
}
2
3
4
5
6
7
8
9
# React.isValidElement 判断原理
判断传入对象上的 $$typeof 是否是 Symbol(react.fragment)
符号
const REACT_ELEMENT_TYPE = Symbol.for('react.element')
function isValidElement(object) {
return typeof object === "object" && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
}
2
3
4
# React 组件
React 只包含两种:class 类组件与 function 组件
class 类组件需要继承 React.Component 或 React.PureComponet
方法创建,否则报错
组件本质由 React 元素组成
# 判断 React 组件类型
只要判断各自的原型链上是否存在 isReactComponent
,存在且为真,则 class 组件,否则是函数组件
// ture -> class 组件,false -> function 组件,但他们都是 react 组件
function isReactComponent(comp) {
return typeof comp === 'function' && !!comp.prototype.isReactComponent
}
2
3
4
如果不考虑将 ES6 代码转换为 ES5 代码的话,通过 class 或 function 关键字判断
如果将 class 转换为 function 的话,此判断就失效了,毕竟 class 是 function 语法糖
// ture -> class 组件,false -> function 组件,但他们都是 react 组件
function isReactClassComponent(comp) {
return isReactComponent(comp) && comp.toSring().startsWith('class')
}
2
3
4
class 组件分为 PureComponet 与 Component 两种,判断如下:
// ture -> PureComponet,false -> Component
function isReactClassComponent(comp) {
return isReactComponent(comp) && comp.prototype.isPureReactComponent
}
2
3
4
# React 元素与组件的关联图
# 小结
React 元素组成 React 组件
React 元素通过 React.isValidElement 方法判断
本质是判断 React 原型的 $$typeof 字段
直接声明的 React 元素是 DOM 类型,由 class 或 function 创建的是合成类型
通过 React 元素的 type 判断
React 组件通过原型链上的 isReactComponent 判断
React 组件分为 class 与 function 类型
class 类型又分为 Component 类型与 PureComponent 类型
通过原型链上的 isPureReactComponent 判断
以上,提供了一个好用的检查工具包react-type-check (opens new window)
扫一扫,微信中打开