Created
April 18, 2023 17:25
-
-
Save mstewartgallus/a95bf10d37e0b12ab549449eb5ba753e to your computer and use it in GitHub Desktop.
Mostly silly because you can just use an error boundary utility based around https://react.dev/reference/react/Component#static-getderivedstatefromerror
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
lazy, Suspense, | |
createContext, useCallback, useContext, useEffect, useReducer, useTransition | |
} from "react"; | |
const initialState = { | |
poison: false, | |
throwable: undefined | |
}; | |
const reducer = (state, throwable) => { | |
if (state.poison) { | |
return state; | |
} | |
return { poison: true, throwable }; | |
}; | |
const useJump = () => { | |
const [, startTransition] = useTransition(); | |
const [{ poison, throwable }, dispatch] = useReducer(reducer, initialState); | |
const jump = useCallback(x => startTransition(() => dispatch(x)), []); | |
return { poison, throwable, jump }; | |
}; | |
const throwStub = throwable => { | |
throw throwable; | |
}; | |
// FIXME use Suspense ? | |
const createException = (displayName, defaultHandler = null) => { | |
const Ex = createContext(defaultHandler ?? throwStub); | |
Ex.displayName = displayName; | |
const { Provider } = Ex; | |
const useThrow = throwable => { | |
const jump = useContext(Ex); | |
// FIXME slow? You can't update component while inside a | |
// different component without an indirection like useEffect. | |
useEffect(() => jump(throwable), [throwable, jump]); | |
}; | |
const Throw = ({value}) => { | |
useThrow(value); | |
return null; | |
}; | |
const Catch = ({children, fallback}) => { | |
const { poison, throwable, jump } = useJump(); | |
return poison ? | |
fallback(throwable) : | |
<Provider value={jump}> | |
{children} | |
</Provider>; | |
}; | |
return { Throw, Catch }; | |
}; | |
const Foo = createException('Foo'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment