Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sjv improve error logging #597

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 125 additions & 7 deletions packages/react-server-test-pages/pages/error/logs.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,134 @@
import Q from "q";
import Q from 'q';
import { Component } from 'react';
import { RootElement } from 'react-server';

import {RootElement} from "react-server";
class RenderError extends Component {
render() {
throw new Error('Error in render');
}
}

const ReceiveProps = OriginalComponent => class extends Component {
constructor(props) {
super(props);
this.state = {
randomProp: Math.random(),
};
}
updateState() {
this.setState({
randomProp: Math.random(),
});
}
render() {
return (
<h2>
<button onClick={this.updateState.bind(this)}>
Click to update props
</button>
<OriginalComponent {...this.state}/>
</h2>
);
}
};

const ComponentWillReceivePropsError = ReceiveProps(
class extends Component {
componentWillReceiveProps(nextProps) {
throw Error('Error in componentWillReceiveProps');
}
render() {
return <span>componentWillReceiveProps error</span>;
}
}
);

const ComponentDidReceivePropsError = ReceiveProps(
class extends Component {
componentDidReceiveProps(nextProps) {
throw Error('Error in componentDidReceiveProps');
}
render() {
return <span>componentDidReceiveProps error</span>;
}
}
);

const ComponentWillUpdateError = ReceiveProps(
class extends Component {
componentWillUpdate(nextProps, nextState) {
throw Error('Error in componentWillUpdate');
}
render() {
return <span>componentWillUpdate error</span>;
}
}
);

const ComponentDidUpdateError = ReceiveProps(
class extends Component {
componentDidUpdate(prevProps, prevState) {
throw Error('Error in componentDidUpdate');
}
render() {
return <span>componentDidUpdate error</span>;
}
}
);

class ComponentDidMountError extends Component {
componentDidMount() {
throw Error('Error in componentDidMount');
}
render() {
return <h2>componentDidMount Error</h2>;
}
}

class ComponentWillMountError extends Component {
componentWillMount() {
throw Error('Error in componentWillMount');
}
render() {
return <h2>componentWillMount Error</h2>;
}
}

function fail() {
return Q().then(() => { throw new Error("Fail!") });
return Q().then(() => { throw new Error('Fail'); });
}

const RootElementWhenPromiseFailure = (props =>
<RootElement when={fail()}>
<h2>RootElement when=failed promise</h2>
</RootElement>
);

class MissingKeyPropInArrayIterator extends Component {
render() {
return (
<div>
<h2>Missing Key Prop in Array Iterator Warning</h2>
{ [1,2,3,4].map(n => <span>{n}</span>) }
</div>
);
}
}

export default class ErrorLogsPage {
export default class ErrorReportingPage {
getElements() {
return [
<div>Check the logs</div>,
<RootElement when={fail()}>Nope</RootElement>,
]
<h1>Error Logging Tests</h1>,
<h2>Render error</h2>,
<RenderError/>,
<ComponentWillMountError/>,
<ComponentDidMountError/>,
<ComponentWillReceivePropsError/>,
<ComponentDidReceivePropsError/>,
<ComponentWillUpdateError/>,
<ComponentDidUpdateError/>,
<RootElementWhenPromiseFailure/>,
<MissingKeyPropInArrayIterator/>,
];
}
}
21 changes: 15 additions & 6 deletions packages/react-server/core/ClientController.js
Original file line number Diff line number Diff line change
Expand Up @@ -648,12 +648,21 @@ class ClientController extends EventEmitter {
// Always render in order to proritize content higher in the
// page.
//
elementPromises.reduce((chain, promise, index) => chain.then(
() => promise.then(element => rootNodePromises[index]
.then(root => renderElement(element, root, index))
.catch(e => logger.error(`Error with element render ${index}`, e))
).catch(e => logger.error(`Error with element promise ${index}`, e))
), Q()).then(retval.resolve);
elementPromises.reduce((chain, promise, index) => chain
.then(() => promise
.then(element => rootNodePromises[index]
.then(root => renderElement(element, root, index))
.catch(e => {
// The only case where this should evaluate to false is
// when `element` is a containerClose/containerOpen object
const componentType = typeof element.type === 'function'
? element.props.children.type.name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoa, does this always work? Can we ditch PageUtil.getElementDisplayName (or gut it and put this in there)?

: 'element';
logger.error(`Error with ${componentType} render ${index}`, e);
})
).catch(e => logger.error(`Error with element promise ${index}`, e))
),
Q()).then(retval.resolve);

// Look out for a failsafe timeout from the server on our
// first render.
Expand Down