Effect collects all expected errors inside the second type parameter of the Effect
type. In our example, we expect two possible errors:
HttpClientError
: When the request fails for any reasonParseError
: When the response body doesn't match the schema
We are going to see one way to handle these errors.
Effect offers multiple APIs to handle errors. We are going to use a few of them that are convenient for this example.
We use Effect.match
to return a JSX element for both failure and success cases:
export default async function HomePage() {
return (
<div>
<title>Index</title>
{await RuntimeServer.runPromise(
main.pipe(
Effect.match({
onFailure: (error) => /// Show error information
onSuccess: (posts) => (
<div>
{posts.map((post) => (
<div key={post.id}>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
))}
</div>
),
})
)
)}
</div>
);
}
Exhaustive pattern matching on all errors
Using the Match
module of effect we can make sure at compile time to handle all possible errors (exhaustive pattern matching).
We do this with Match.valueTags
. For each error we provide a component that displays an error message:
export default async function HomePage() {
return (
<div>
<title>Index</title>
{await RuntimeServer.runPromise(
main.pipe(
Effect.match({
onFailure: Match.valueTags({
ParseError: (error) => <span>ParseError</span>,
RequestError: (error) => <span>RequestError</span>,
ResponseError: (error) => <span>ResponseError</span>,
}),
onSuccess: (posts) => (
<div>
{posts.map((post) => (
<div key={post.id}>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
))}
</div>
),
})
)
)}
</div>
);
}
With this we handled all the expected errors. You can go ahead and add more details about each error if necessary.
Each error case inside
Match.valueTags
has access to the original error value, so you can use it to display more details.