Error boundaries and error handling
Answered
Spinge Bib Sqorpnts posted this in #help-forum
Hello! Currently, I'm triggering an error, on purpose, in a
In development, it shows the Next.js error window, without triggering any error boundaries (I got an
In production, it does not show anything, except the error in the browser's console.
.ts file, in a function called from a Component's useEffect hook.In development, it shows the Next.js error window, without triggering any error boundaries (I got an
error.tsx, global-error.tsx and react-error-boundary) and of course, logs the error in the browser's console.In production, it does not show anything, except the error in the browser's console.
Answered by ᴉuɐpɹɐɐ
const try = (cb) => {
return (...args) => {
try {
await cb(...args)
} catch (error) {
console.log(error || "Smth went wrong, fix asap / handle these erros")
toast(error || "Somth went wrong")
}
}
}21 Replies
@Spinge Bib Sqorpnts Hello! Currently, I'm triggering an error, on purpose, in a `.ts` file, in a function called from a Component's useEffect hook.
In development, it shows the Next.js error window, without triggering any error boundaries (I got an `error.tsx`, `global-error.tsx` and `react-error-boundary`) and of course, logs the error in the browser's console.
In production, it does not show anything, except the error in the browser's console.
errors thrown in useEffect or event handlers aren't caught in the error boundary. errors thrown during rendering like below are caught by the boundary:
// can be server comp or client comp
function Component() {
if (...) throw new Error(...);
return <div>...</div>;
}@joulev errors thrown in useEffect or event handlers aren't caught in the error boundary. errors thrown during rendering like below are caught by the boundary:
tsx
// can be server comp or client comp
function Component() {
if (...) throw new Error(...);
return <div>...</div>;
}
how can I handle errors thrown in useEffects and EventHandlers?
other than try/catch everywhere
you can make a reusable function and wrap your useEffects and eventHandlers
and only used try catch once
why do you want to know how to handle errors without using try/catch?
@ᴉuɐpɹɐɐ why do you want to know how to handle errors without using try/catch?
The project has gone quite far, while overlooking the fact that ErrorBoundaries don't affect useEffects and eventHandlers, so adding try/catch everywhere would be one helluva task
Was it bad practice to not put error handling? sure
Did I write all the code? nope
Does the code sometimes error in places where nobody expected any error? yes
Did I write all the code? nope
Does the code sometimes error in places where nobody expected any error? yes
and the most problematic thing is the third line
because what if an error pops up in an unexpected/missed place?
yep, reusable funciton it is
const try = (cb) => {
return (...args) => {
try {
await cb(...args)
} catch (error) {
console.log(error || "Smth went wrong, fix asap / handle these erros")
toast(error || "Somth went wrong")
}
}
}Answer
I guess that's better than nothing
thanks a lot :)
I wonder, if I can somehow modify useEffect so its wrapped in a function and is just a drop-in replacement
ill look into it
thanks again
Japanese pilchard
You could 100% create your own
I recall this article having a helpful example of the difference between traditional
It's targeted more at explaining
useEffect that does the same thing and modify all the imports, although I'd prefer @ᴉuɐpɹɐɐ's method in that case.I recall this article having a helpful example of the difference between traditional
useEffect and Suspense/ErrorBoundary: https://dev.to/smitterhane/swap-out-useeffect-with-suspense-for-data-fetching-in-react-2lebIt's targeted more at explaining
Suspense, but ErrorBoundary basically works the same way. If the render function throws (or returns) a Promise, then React will try to use the nearest Suspense ancestor. If it throws an Error, that will propagate up to the nearest ErrorBoundary. You can see how this is triggered in the helper function returned by fetchPosts:return () => {
if (status === "pending") {
throw fetching; // Suspend(A way to tell React data is still fetching)
} else if (status === "rejected") {
throw result; // Result is an error
} else if (status === "fulfilled") {
return result; // Result is a fulfilled promise
}
};The main problem is that
useEffect puts the wrapped function into the task executor, so it won't be executed as part of the render and thus won't propagate up the tree in the same way.You could instead write your own
useEffect wrapper and UseEffectErrorBoundary, which would essentially be a Context.Provider. If the callback in the useEffect throws, set the Error on the context and render the fallback component. Same principle basically applies for a UseEffectSuspense if you want, with a loading state and fallback component.Donskoy
Based on the docs I understood that error.js file also covers the page.js file within the same folder, but not the layout.js. Hoverer, in practice, adding an error.js file in the same folder with page.js did not catch any errors, I had to rather add error.js file in the parent directory, in order to catch errors in the nested page.js. Can someone confirm that the docs are indeed incorrect?