S
SolidJSā€¢4mo ago
mykola

handling (http) errors with createResource

I don't understand how to get hold of the error when using the tutorial examples of fetching REST data. The error is always either empty, or not callable to me ("solid-js": "^1.8.11"). If I take the example from the documentation here and make it work. I shows the fetched data OK, but doesn't handle http404's. OK, I modify the fetchUser function to throw on non-ok:
const fetchUser = async (id) => {
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
if (!response.ok) {
throw Error(`Response not ok ${response.status}`);
}
return response.json();
};

function App() {
const [userId, setUserId] = createSignal();
const [user] = createResource(userId, fetchUser);

return (
<div>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<Show when={user.loading}>
<p>Loading...</p>
</Show>
<Switch>
<Match when={user.error}>
<span>Error: {user.error()}</span>
</Match>
<Match when={user()}>
<div>{JSON.stringify(user())}</div>
</Match>
</Switch>
</div>
);
}
const fetchUser = async (id) => {
const response = await fetch(`https://swapi.dev/api/people/${id}/`);
if (!response.ok) {
throw Error(`Response not ok ${response.status}`);
}
return response.json();
};

function App() {
const [userId, setUserId] = createSignal();
const [user] = createResource(userId, fetchUser);

return (
<div>
<input
type="number"
min="1"
placeholder="Enter Numeric Id"
onInput={(e) => setUserId(e.currentTarget.value)}
/>
<Show when={user.loading}>
<p>Loading...</p>
</Show>
<Switch>
<Match when={user.error}>
<span>Error: {user.error()}</span>
</Match>
<Match when={user()}>
<div>{JSON.stringify(user())}</div>
</Match>
</Switch>
</div>
);
}
the rendering gets broken because the user.error() isn't a function šŸ¤”
Uncaught (in promise) TypeError: user.error is not a function
Uncaught (in promise) TypeError: user.error is not a function
When I replace user.error() with the typeOf and JSON.stringify, they show an empty object {}.
<Match when={user.error}>
<span>Error: {typeof(user.error)} {JSON.stringify(user.error)}</span>
</Match>
<Match when={user.error}>
<span>Error: {typeof(user.error)} {JSON.stringify(user.error)}</span>
</Match>
ā“ What do I do wrong, and how to get the resource errors reported properly? I tried Promised.reject(new Error(...)) and axios.get with no change in behavior. Playground example: https://playground.solidjs.com/anonymous/3b5dbdc3-c242-4d24-8468-f7b5c98509ed
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
7 Replies
Brendonovich
Brendonovichā€¢4mo ago
Values thrown in resources get caught by ErrorBoundary components above where the resource is read
mykola
mykolaOPā€¢4mo ago
Hey @Brendonovich , thank you for the quick reaction. Yes, an ErrorBoundary around the App component does indeed catch the error thrown (if I remove the match on user.error). Could make it work for some cases, but looks like a hack to me, since (AFAIU) the ErrorBoundaries are supposed to prevent whole applications crash from unexpected errors, not to handle the expected ones. I would like to have a more fine-grained control over the error handling, e.g. show an error saying "User doesn't exist" under the userId input - not replace the whole component with the wrapping fallback of the ErrorBoundary. Which, AFAIU, the examples in the documentation are trying to show me how to do, but something is amiss.
Brendonovich
Brendonovichā€¢4mo ago
You can put an error boundary around the Show and Match as well, but from what I understand in this case you're receiving specific errors that you want to display. I'd recommend not throwing these, instead return them as data. Rely on thrown errors for unrecoverable problems
mykola
mykolaOPā€¢4mo ago
OK, so what you're saying you wouldn't be relying on the error of the createResource . āœ…
Brendonovich
Brendonovichā€¢4mo ago
Yeah, send everything that you want to display specific UI for through data That also has the added benefit of being typesafe, so you can type narrow in Switch/Match
mykola
mykolaOPā€¢4mo ago
OK, so at the end it was a bug in the documentation, where they used user.error() instead of the user.error for const user = createResource(...). Submitting a PR with a fix suggestion: https://github.com/solidjs/solid-docs-next/pull/847
Brendonovich
Brendonovichā€¢4mo ago
ah yea those are wrong
Want results from more Discord servers?
Add your server