diff --git a/js/components/errorHandling/errorBoundary.js b/js/components/errorHandling/errorBoundary.js index 0e07697b4..b4b24a3c9 100644 --- a/js/components/errorHandling/errorBoundary.js +++ b/js/components/errorHandling/errorBoundary.js @@ -10,43 +10,52 @@ import { snackbarColors } from '../header/constants'; export class ErrorBoundary extends Component { constructor(props) { super(props); - this.state = { error: null, errorInfo: null }; + this.state = { caughtError: null, errorInfo: null }; } - componentDidCatch(error, errorInfo) { - // Catch errors in any components below and re-render with error message - this.setState({ - error: error, - errorInfo: errorInfo - }); + handleErrorData(error, errorInfo) { // You can also log error messages to an error reporting service here if (process.env.NODE_ENV === 'production') { - Sentry.configureScope(scope => { - Object.keys(errorInfo).forEach(key => { - scope.setExtra(key, errorInfo[key]); + if (errorInfo) { + Sentry.configureScope(scope => { + Object.keys(errorInfo).forEach(key => { + scope.setExtra(key, errorInfo[key]); + }); }); - }); + } Sentry.captureException(error); } } + componentDidCatch(error, errorInfo) { + // Catch errors in any components below and re-render with error message + this.setState({ + caughtError: error, + errorInfo: errorInfo + }); + this.handleErrorData(error, errorInfo); + } + render() { const { children } = this.props; - const { error } = this.state; + const { caughtError } = this.state; //render fallback UI return ( <> {children} - {error !== null && ( - - {({ setSnackBarTitle, setSnackBarColor }) => { + + {({ error, setSnackBarTitle, setSnackBarColor }) => { + if (error || caughtError !== null) { + if (error) { + this.handleErrorData(error); + } setSnackBarTitle('Something went wrong!'); - setSnackBarColor(snackbarColors.default); - return null; - }} - - )} + setSnackBarColor(snackbarColors.error); + } + return null; + }} + ); } diff --git a/js/components/header/headerContext.js b/js/components/header/headerContext.js index 7fc0a3d04..1c10d59d1 100644 --- a/js/components/header/headerContext.js +++ b/js/components/header/headerContext.js @@ -10,6 +10,7 @@ export const HeaderProvider = memo(props => { const [headerButtons, setHeaderButtons] = useState(null); const [snackBarTitle, setSnackBarTitle] = useState(null); const [snackBarColor, setSnackBarColor] = useState(snackbarColors.default); + const [error, setError] = useState(); return ( { snackBarTitle, setSnackBarTitle, snackBarColor, - setSnackBarColor + setSnackBarColor, + error, + setError }} > {props.children} diff --git a/js/components/landing/Landing.js b/js/components/landing/Landing.js index bf25ac02a..fb90a8785 100644 --- a/js/components/landing/Landing.js +++ b/js/components/landing/Landing.js @@ -2,7 +2,7 @@ * Created by ricgillams on 21/06/2018. */ import { Grid } from '@material-ui/core'; -import React, { memo, useEffect, useState } from 'react'; +import React, { memo, useEffect } from 'react'; import TargetList from '../target/targetList'; import SessionList from '../session/sessionList'; import { connect } from 'react-redux'; @@ -11,7 +11,6 @@ import * as selectionActions from '../../reducers/selection/actions'; import { DJANGO_CONTEXT } from '../../utils/djangoContext'; const Landing = memo(({ resetSelectionState, resetTargetState }) => { - const [state, setState] = useState(); let text_div; if (DJANGO_CONTEXT['authenticated'] === true) { @@ -37,15 +36,7 @@ const Landing = memo(({ resetSelectionState, resetTargetState }) => { -

{ - setState(() => { - throw Error('my custom error'); - }); - }} - > - Welcome to Fragalysis -

+

Welcome to Fragalysis

{text_div}
diff --git a/js/components/preview/compounds/compoundView.js b/js/components/preview/compounds/compoundView.js index 873ad185f..4d0b415ed 100644 --- a/js/components/preview/compounds/compoundView.js +++ b/js/components/preview/compounds/compoundView.js @@ -8,6 +8,7 @@ import { VIEWS } from '../../../constants/constants'; import { NglContext } from '../../nglView/nglProvider'; import { compoundsColors } from './redux/constants'; import { handleClickOnCompound, loadCompoundImageData } from './redux/dispatchActions'; +import { HeaderContext } from '../../header/headerContext'; export const loadingCompoundImage = ` @@ -23,19 +24,17 @@ export const CompoundView = memo(({ height, width, data, index }) => { const majorViewStage = getNglView(VIEWS.MAJOR_VIEW).stage; const [image, setImage] = useState(loadingCompoundImage); - const [state, setState] = useState(); + const { setError } = useContext(HeaderContext); useEffect(() => { let onCancel = () => {}; loadCompoundImageData({ width, height, data, onCancel, setImage }).catch(error => { - setState(() => { - throw error; - }); + setError(error); }); return () => { onCancel(); }; - }, [height, width, data]); + }, [height, width, data, setError]); const not_selected_style = { width: (width + 5).toString() + 'px', diff --git a/js/components/preview/hotspot/hotspotList.js b/js/components/preview/hotspot/hotspotList.js index dfd608d81..6efed988b 100644 --- a/js/components/preview/hotspot/hotspotList.js +++ b/js/components/preview/hotspot/hotspotList.js @@ -1,7 +1,7 @@ /** * Created by ricgillams on 04/07/2018. */ -import React, { memo, useState, useEffect, useCallback, useRef } from 'react'; +import React, { memo, useState, useEffect, useCallback, useRef, useContext } from 'react'; import { connect } from 'react-redux'; import * as apiActions from '../../../reducers/api/actions'; import * as listType from '../../../constants/listTypes'; @@ -9,10 +9,11 @@ import HotspotView from './hotspotView'; import { getUrl, loadFromServer } from '../../../utils/genericList'; import { api, METHOD } from '../../../utils/api'; import { Paper } from '../../common/Surfaces/Paper'; +import { HeaderContext } from '../../header/headerContext'; const molStyle = { height: '250px', overflow: 'scroll' }; const HotspotList = memo(({ molecule_list, setObjectList, target_on, mol_group_on }) => { - const [state, setState] = useState(); + const { setError } = useContext(HeaderContext); const list_type = listType.MOLECULE; const oldUrl = useRef(''); const setOldUrl = url => { @@ -36,15 +37,13 @@ const HotspotList = memo(({ molecule_list, setObjectList, target_on, mol_group_o setHsCount(response.data); }) .catch(error => { - setState(() => { - throw error; - }); + setError(error); }); return () => { onCancel(); }; } - }, [molecule_list]); + }, [molecule_list, setError]); useEffect(() => { updateCount(); @@ -60,14 +59,12 @@ const HotspotList = memo(({ molecule_list, setObjectList, target_on, mol_group_o setObjectList, cancel: onCancel }).catch(error => { - setState(() => { - throw error; - }); + setError(error); }); return () => { onCancel(); }; - }, [list_type, setObjectList, mol_group_on, target_on]); + }, [list_type, setObjectList, mol_group_on, target_on, setError]); if (hsCount > 0) { return ( diff --git a/js/components/preview/molecule/moleculeList.js b/js/components/preview/molecule/moleculeList.js index 35358f855..c8f6d5a98 100644 --- a/js/components/preview/molecule/moleculeList.js +++ b/js/components/preview/molecule/moleculeList.js @@ -4,7 +4,7 @@ import { Grid, Chip, Tooltip, makeStyles, CircularProgress, Divider, Typography } from '@material-ui/core'; import { FilterList } from '@material-ui/icons'; -import React, { useState, useEffect, memo, useRef } from 'react'; +import React, { useState, useEffect, memo, useRef, useContext } from 'react'; import { connect } from 'react-redux'; import * as apiActions from '../../../reducers/api/actions'; import * as listType from '../../../constants/listTypes'; @@ -19,6 +19,7 @@ import { Panel } from '../../common/Surfaces/Panel'; import { ComputeSize } from '../../../utils/computeSize'; import { moleculeProperty } from './helperConstants'; import { setSortDialogOpen } from './redux/actions'; +import { HeaderContext } from '../../header/headerContext'; const useStyles = makeStyles(theme => ({ container: { @@ -110,7 +111,7 @@ const MoleculeList = memo( const classes = useStyles(); const list_type = listType.MOLECULE; const oldUrl = useRef(''); - const [state, setState] = useState(); + const { setError } = useContext(HeaderContext); const setOldUrl = url => { oldUrl.current = url; }; @@ -154,11 +155,9 @@ const MoleculeList = memo( mol_group_on, cached_mol_lists }).catch(error => { - setState(() => { - throw error; - }); + setError(error); }); - }, [list_type, mol_group_on, setMoleculeList, target_on, setCachedMolLists, cached_mol_lists]); + }, [list_type, mol_group_on, setMoleculeList, target_on, setCachedMolLists, cached_mol_lists, setError]); const listItemOffset = (currentPage + 1) * moleculesPerPage; const currentMolecules = joinedMoleculeLists.slice(0, listItemOffset); diff --git a/js/components/preview/molecule/moleculeView.js b/js/components/preview/molecule/moleculeView.js index 48a67f30d..13f8a8e17 100644 --- a/js/components/preview/molecule/moleculeView.js +++ b/js/components/preview/molecule/moleculeView.js @@ -18,6 +18,7 @@ import { moleculeProperty } from './helperConstants'; import { api } from '../../../utils/api'; import { generateObjectList } from '../../session/helpers'; import { getTotalCountOfCompounds } from './molecules_helpers'; +import { HeaderContext } from '../../header/headerContext'; const useStyles = makeStyles(theme => ({ container: { @@ -116,7 +117,7 @@ export const img_data_init = `