prevent rendering loop when using handle error

This commit is contained in:
Annika Hannig 2022-06-20 10:27:14 +02:00
parent da87e3e4ca
commit 0bc219065d
4 changed files with 24 additions and 10 deletions

View File

@ -14,7 +14,7 @@ import { createContext
}
from 'react';
import { useErrors }
import { useErrorHandler }
from 'app/components/errors/Provider';
const initialState = {
@ -45,7 +45,7 @@ export const useConfig = () => useContext(ConfigContext);
const ConfigProvider = ({children}) => {
const [config, setConfig] = useState(initialState);
const [handleError] = useErrors();
const handleError = useErrorHandler();
// OnLoad: once
useEffect(() => {

View File

@ -5,6 +5,7 @@
import { useState
, createContext
, useContext
, useRef
, useCallback
}
from 'react';
@ -13,6 +14,11 @@ import { useState
const ErrorContext = createContext(null);
export const useErrors = () => useContext(ErrorContext);
export const useErrorHandler = () => {
const [handleRef] = useErrors();
return useCallback((err) => handleRef.current(err), [handleRef]);
};
// Unfortunatley this does not really act as an error
// boundary. But we need to catch http errors from axios.
@ -20,11 +26,13 @@ export const useErrors = () => useContext(ErrorContext);
const ErrorProvider = ({children}) => {
const [errors, setErrors] = useState([]);
// Handle prepends the error to the state
const handle = useCallback((err) => {
// Handle prepends the error to the state.
// Use a ref to the handler function to prevent
// a rendering loop.
const handle = (err) => {
setErrors([err, ...errors]);
}, [errors]);
};
const handleRef = useRef(handle);
// Dismiss removes the error from the state
const dismiss = (err) => {
@ -32,7 +40,7 @@ const ErrorProvider = ({children}) => {
setErrors(filtered);
}
const ctx = [handle, dismiss, errors];
const ctx = [handleRef, dismiss, errors];
return (
<ErrorContext.Provider value={ctx}>
{children}

View File

@ -9,7 +9,7 @@ import { useEffect
import { Link }
from 'react-router-dom';
import { useErrors }
import { useErrorHandler }
from 'app/components/errors/Provider';
import { useRouteServers }
from 'app/components/routeservers/Provider';
@ -21,7 +21,7 @@ const Status = ({routeServerId}) => {
version: "",
});
const [error, setError] = useState(null);
const [handleError] = useErrors();
const handleError = useErrorHandler();
useEffect(() => {
axios.get(`/api/v1/routeservers/${routeServerId}/status`)
@ -31,7 +31,7 @@ const Status = ({routeServerId}) => {
handleError(error);
setError(error); // Local error display
});
}, [routeServerId, handleError, setError]);
}, [routeServerId, handleError]);
if (error && error.code >= 100 && error.code < 200) {

View File

@ -11,6 +11,7 @@ import { useState
, useEffect
, useContext
, createContext
, useRef
}
from 'react';
@ -28,16 +29,21 @@ export const useRouteServers = () => useContext(RouteServersContext);
* backend and uses these as provider value.
*/
const RouteServersProvider = ({children}) => {
const init = useRef();
const [handleError] = useErrors();
const [rs, setRs] = useState([]);
// Load route servers from backend
useEffect(() => {
if (init.current) {
return;
}
axios.get('/api/v1/routeservers')
.then(
({data}) => setRs(data.routeservers),
(error) => handleError(error)
);
init.current = true;
}, [handleError]);
return (