Improve error logging for event handlers of React components.
This guards every auto-bound method and uses the name of the component and method as guard name.
Felix Kling committed
Nov 8, 2013 at 16:53 UTC
1e71df5399e4c94511e587fa368e7c57a537dc91
3 files changed
+95
-1
src/core/ReactCompositeComponent.js
+5
-1
@@ -20,6 +20,7 @@
20
21
var ReactComponent = require('ReactComponent');
22
var ReactCurrentOwner = require('ReactCurrentOwner');
23
+var ReactErrorUtils = require('ReactErrorUtils');
24
var ReactOwner = require('ReactOwner');
25
var ReactPerf = require('ReactPerf');
26
var ReactPropTransferer = require('ReactPropTransferer');
@@ -877,7 +878,10 @@ var ReactCompositeComponentMixin = {
878
continue;
879
}
880
var method = this.__reactAutoBindMap[autoBindKey];
880
- this[autoBindKey] = this._bindAutoBindMethod(method);
881
+ this[autoBindKey] = ReactErrorUtils.guard(
882
+ this._bindAutoBindMethod(method),
883
+ this.constructor.displayName + '.' + autoBindKey
884
+ );
885
}
886
},
887
src/core/__tests__/ReactCompositeComponentError-test.js
new
+46
@@ -0,0 +1,46 @@
1
+/**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @jsx React.DOM
17
+ * @emails react-core
18
+ */
19
+
20
+"use strict";
21
+
22
+var React = require('React');
23
+var ReactTestUtils = require('ReactTestUtils');
24
+var ReactErrorUtils;
25
+
26
+describe('ReactCompositeComponent-error', function() {
27
+
28
+ beforeEach(function() {
29
+ ReactErrorUtils = require('ReactErrorUtils');
30
+ });
31
+
32
+ it('should be passed the component and method name', function() {
33
+ var Component = React.createClass({
34
+ someHandler: function() {},
35
+ render: function() {
36
+ return <div />;
37
+ }
38
+ });
39
+
40
+ var instance = <Component />;
41
+ ReactTestUtils.renderIntoDocument(instance);
42
+ expect(ReactErrorUtils.guard.mock.calls[0][1])
43
+ .toEqual('Component.someHandler');
44
+ });
45
+
46
+});
src/vendor/stubs/ReactErrorUtils.js
new
+44
@@ -0,0 +1,44 @@
1
+/**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactErrorUtils
17
+ * @typechecks
18
+ */
19
+
20
+var ReactErrorUtils = {
21
+ /**
22
+ * Creates a guarded version of a function. This is supposed to make debugging
23
+ * of event handlers easier. This implementation provides only basic error
24
+ * logging and re-throws the error.
25
+ *
26
+ * @param {function} func Function to be executed
27
+ * @param {string} name The name of the guard
28
+ * @return {function}
29
+ */
30
+ guard: function(func, name) {
31
+ return function guarded() {
32
+ try {
33
+ return func.apply(this, arguments);
34
+ } catch(ex) {
35
+ if (__DEV__) {
36
+ console.error(name + ': ' + ex.message);
37
+ }
38
+ throw ex;
39
+ }
40
+ };
41
+ }
42
+};
43
+
44
+module.exports = ReactErrorUtils;