-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy patherror-catch.js
More file actions
96 lines (85 loc) · 2.8 KB
/
error-catch.js
File metadata and controls
96 lines (85 loc) · 2.8 KB
1
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import React from 'react';
import reporter from './reporter';
import isPlainObject from 'lodash.isplainobject';
const fixedFuncMap = new Map();
class ReactCatcher {
constructor() {
this._elError = null;
this._errCallback = null;
this.init();
}
set(config = {}) {
this._elError = config.elError || null;
}
init() {
const originalCreateElement = React.createElement;
React.createElement = (Component, props, ...children) => {
if (children && children.length) {
children = this.normalizeChildren(...children);
}
// Component必定是function/class或者string,性能考虑不再判断Component类型
if (Component.prototype) {
if (Component.prototype.render) {
this.fixRender(Component);
} else {
Component = this.fixFunction(Component);
}
}
return originalCreateElement.call(React, Component, props, ...children);
};
}
fixRender(Component) {
if (Component.__handled) {
return;
}
const prototype = Component.prototype;
const originalRender = prototype.render;
const elError = this._elError;
prototype.render = function() {
try {
return originalRender.call(this);
} catch (e) {
reporter.report(e, Component.name);
return elError || null;
}
};
Component.__handled = true;
}
fixFunction(Component) {
const fixedFunc = fixedFuncMap.get(Component);
if (fixedFunc) {
return fixedFunc;
}
const originalComponent = Component;
Component = (...args) => {
try {
return originalComponent(...args);
} catch (e) {
reporter.report(e, Component.name || String(Component));
return this._elError || null;
}
};
// copy properties like propTypes, defaultProps etc.
Object.assign(Component, originalComponent);
fixedFuncMap.set(originalComponent, Component);
return Component;
}
// catch "Objects are not valid as a React child" error
normalizeChildren(...children) {
return children.map((item) => {
if (!item) {
return item;
}
if (React.isValidElement(item)) {
return item;
}
if (!isPlainObject(item)) {
return item;
}
reporter.report(`[Objects are not valid as a React child]: ${JSON.stringify(item)}`);
return null;
});
}
}
const reactCatcher = new ReactCatcher();
export default reactCatcher;