diff --git a/js/app.js b/js/app.js
index 9e8e3a91..520bedbd 100644
--- a/js/app.js
+++ b/js/app.js
@@ -5,8 +5,6 @@ require('babel/polyfill');
import React from 'react';
import { Router, Redirect } from 'react-router';
import history from './history';
-import { ReactError, ResourceNotFoundError } from './react_error.js';
-import { ResourceNotFoundErrorHandler } from './react_error_handlers';
/* eslint-disable */
import fetch from 'isomorphic-fetch';
@@ -93,20 +91,12 @@ class AppGateway {
// us in that case.
history.listen(EventActions.routeDidChange);
- ReactError({
- render: React.render,
- params: [(
-
- {redirectRoute}
- {getRoutes(type, subdomain)}
-
- ),
- document.getElementById('main')],
- errors: [{
- error: ResourceNotFoundError,
- handler: ResourceNotFoundErrorHandler
- }]
- });
+ React.render((
+
+ {redirectRoute}
+ {getRoutes(type, subdomain)}
+
+ ), document.getElementById('main'));
// Send the applicationDidBoot event to the third-party stores
EventActions.applicationDidBoot(settings);
diff --git a/js/components/ascribe_detail/edition_container.js b/js/components/ascribe_detail/edition_container.js
index af7b7928..189f7e60 100644
--- a/js/components/ascribe_detail/edition_container.js
+++ b/js/components/ascribe_detail/edition_container.js
@@ -3,6 +3,9 @@
import React from 'react';
import { History } from 'react-router';
+import ReactError from '../../mixins/react_error';
+import { ResourceNotFoundError } from '../../models/errors';
+
import EditionActions from '../../actions/edition_actions';
import EditionStore from '../../stores/edition_store';
@@ -10,6 +13,7 @@ import Edition from './edition';
import AscribeSpinner from '../ascribe_spinner';
+import { getLangText } from '../../utils/lang_utils';
import { setDocumentTitle } from '../../utils/dom_utils';
@@ -21,7 +25,7 @@ let EditionContainer = React.createClass({
params: React.PropTypes.object
},
- mixins: [History],
+ mixins: [History, ReactError],
getInitialState() {
return EditionStore.getState();
@@ -33,14 +37,7 @@ let EditionContainer = React.createClass({
// as it will otherwise display wrong/old data once the user loads
// the edition detail a second time
EditionActions.updateEdition({});
-
EditionStore.listen(this.onChange);
-
- // Every time we enter the edition detail page, just reset the edition
- // store as it will otherwise display wrong/old data once the user loads
- // the edition detail a second time
- EditionActions.updateEdition({});
-
this.loadEdition();
},
@@ -57,9 +54,7 @@ let EditionContainer = React.createClass({
const { editionError } = this.state;
if(editionError && editionError.status === 404) {
- // Even though the /404 path doesn't really exist,
- // we can still redirect there and the page will show up
- this.history.pushState(null, '/404');
+ this.throws(new ResourceNotFoundError(getLangText('Ups, the edition you\'re looking for doesn\'t exist.')));
}
},
diff --git a/js/components/ascribe_detail/piece_container.js b/js/components/ascribe_detail/piece_container.js
index 187c53c1..5198e6ac 100644
--- a/js/components/ascribe_detail/piece_container.js
+++ b/js/components/ascribe_detail/piece_container.js
@@ -4,6 +4,9 @@ import React from 'react';
import { History } from 'react-router';
import Moment from 'moment';
+import ReactError from '../../mixins/react_error';
+import { ResourceNotFoundError } from '../../models/errors';
+
import PieceActions from '../../actions/piece_actions';
import PieceStore from '../../stores/piece_store';
@@ -53,7 +56,7 @@ let PieceContainer = React.createClass({
params: React.PropTypes.object
},
- mixins: [History],
+ mixins: [History, ReactError],
getInitialState() {
return mergeOptions(
@@ -91,9 +94,7 @@ let PieceContainer = React.createClass({
const { pieceError } = this.state;
if(pieceError && pieceError.status === 404) {
- // Even though this path doesn't exist we can redirect
- // to it as it catches all unknown paths
- this.history.pushState(null, '/404');
+ this.throws(new ResourceNotFoundError(getLangText('Ups, the piece you\'re looking for doesn\'t exist.')));
}
},
diff --git a/js/components/error_not_found_page.js b/js/components/error_not_found_page.js
index 61f83196..670f8629 100644
--- a/js/components/error_not_found_page.js
+++ b/js/components/error_not_found_page.js
@@ -6,6 +6,16 @@ import { getLangText } from '../utils/lang_utils';
let ErrorNotFoundPage = React.createClass({
+ propTypes: {
+ message: React.PropTypes.string
+ },
+
+ getDefaultProps() {
+ return {
+ message: getLangText('Ups, the page you are looking for does not exist.')
+ };
+ },
+
render() {
return (
@@ -13,7 +23,7 @@ let ErrorNotFoundPage = React.createClass({
404
- {getLangText('Ups, the page you are looking for does not exist.')}
+ {this.props.message}
diff --git a/js/mixins/react_error.js b/js/mixins/react_error.js
new file mode 100644
index 00000000..0b7669de
--- /dev/null
+++ b/js/mixins/react_error.js
@@ -0,0 +1,12 @@
+'use strict';
+
+import invariant from 'invariant';
+
+const ReactError = {
+ throws(err) {
+ invariant(err.handler, 'You need to specify a `handler` for this error');
+ err.handler(this, err);
+ }
+};
+
+export default ReactError;
diff --git a/js/models/errors.js b/js/models/errors.js
new file mode 100644
index 00000000..68d97c86
--- /dev/null
+++ b/js/models/errors.js
@@ -0,0 +1,24 @@
+'use strict';
+
+import React from 'react';
+
+import ErrorNotFoundPage from '../components/error_not_found_page';
+
+
+export class ResourceNotFoundError extends Error {
+ constructor(message) {
+ super(message);
+ this.name = this.constructor.name;
+ this.message = message;
+ Error.captureStackTrace(this, this.constructor.name);
+ }
+
+ handler(component, err) {
+ if(!component.state._monkeyPatched) {
+ component.render = () => ;
+ component.setState({
+ _monkeyPatched: true
+ });
+ }
+ }
+}
diff --git a/js/react_error.js b/js/react_error.js
deleted file mode 100644
index 61fb4a70..00000000
--- a/js/react_error.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict';
-
-function _transformErrorsListToHashMap(errors) {
- return errors.reduce((errObj, { error, handler }) => {
- const errorName = error.name;
- if(!errObj[errorName]) {
- errObj[errorName] = {
- error: error,
- handler: handler
- };
- return errObj;
- } else {
- throw new Error('You\'re trying to override the error handler for ' + errorName + ' by specifying it twice.');
- }
- }, {});
-}
-
-export function ReactError({ render, params, errors }) {
- errors = _transformErrorsListToHashMap(errors);
- try {
- // use react's render function + parameters to render
- // the application
- render(...params);
- } catch(err) {
- const potErrorRoutine = errors[err.name];
- if(potErrorRoutine) {
- potErrorRoutine.handler(err);
- } else {
- console.error(err.stack);
- }
- }
-}
-
-// Followed: http://stackoverflow.com/a/32749533/1263876 for extending errors
-export class ResourceNotFoundError extends Error {
- constructor(message) {
- super(message);
- this.name = this.constructor.name;
- this.message = message;
- Error.captureStackTrace(this, this.constructor.name);
- }
-}
\ No newline at end of file
diff --git a/js/react_error_handlers.js b/js/react_error_handlers.js
deleted file mode 100644
index 57366603..00000000
--- a/js/react_error_handlers.js
+++ /dev/null
@@ -1,5 +0,0 @@
-'use strict';
-
-export function ResourceNotFoundErrorHandler() {
- console.log(arguments);
-}
\ No newline at end of file