react 错误边界
by Abi Noda
通过Abi Noda
If you like this article please support me by checking out Pull Reminders, a Slack bot that sends your team automatic reminders for GitHub pull requests.
如果您喜欢本文,请查看Pull Reminders ,这是一个Slack机器人,可以为您的团队发送有关GitHub pull请求的自动提醒,从而为我提供支持。
One challenge I recently ran into while working with GraphQL and React was how to handle errors. As developers, we’ve likely implemented default 500, 404, and 403 pages in server-rendered applications before, but figuring out how to do this with React and GraphQL is tricky.
我最近在使用GraphQL和React时遇到的一个挑战是如何处理错误。 作为开发人员,我们之前可能已经在服务器渲染的应用程序中实现了默认的500、404和403页面,但是弄清楚如何使用React和GraphQL做到这一点很棘手。
In this post, I’ll talk about how our team approached this problem, the final solution we implemented, and interesting lessons from the GraphQL spec.
在本文中,我将讨论我们的团队如何解决此问题,我们实现的最终解决方案以及GraphQL规范中有趣的课程。
The project I was working on was a fairly typical CRUD app built in React using GraphQL, Apollo Client, and express-graphQL. We wanted to handle certain types of errors — for example, the server being down — by displaying a standard error page to the user.
我正在从事的项目是使用GraphQL, Apollo Client和express-graphQL在React中构建的一个相当典型的CRUD应用程序。 我们希望通过向用户显示标准错误页面来处理某些类型的错误(例如,服务器已关闭)。
Our initial challenge was figuring out the best way to communicate errors to the client. GraphQL doesn’t use HTTP status codes like 500, 400, and 403. Instead, responses contain an errors
array with a list of things that went wrong (read more about errors
in the GraphQL spec).
我们最初的挑战是找出向客户传达错误的最佳方法。 GraphQL不使用500、400和403之类的HTTP状态代码。相反,响应包含一个errors
数组,其中包含发生errors
的列表(更多有关GraphQL规范中的 errors
的信息 )。
For example, here’s what our GraphQL response looked like when something broke on the server:
例如,当服务器发生故障时,我们的GraphQL响应如下所示:
Since GraphQL error responses return HTTP status code 200, the only way to identify the kind of error was to inspect the errors
array. This seemed like a poor approach because the error message
property contained the exception thrown on the server. The GraphQL spec states that the value of message
is intended for developers, but it does not specify whether the value should be a human-readable message or something designed to be programmatically handled:
由于GraphQL错误响应返回HTTP状态代码200,因此识别错误类型的唯一方法是检查errors
数组。 这似乎是一种糟糕的方法,因为错误message
属性包含在服务器上引发的异常。 GraphQL规范指出message
的值是供开发人员使用的,但未指定该值是人类可读的消息还是旨在通过编程方式处理的消息:
Every error must contain an entry with the key message with a string description of the error intended for the developer as a guide to understand and correct the error.
每个错误都必须包含带有关键消息的条目,该条目带有针对开发人员的错误字符串说明,以作为开发人员理解和更正错误的指南。
To solve for this, we added standardized error codes to our error objects, which could be used by clients to programmatically identify errors. This was inspired by how Stripe’s REST API returns string error codes in addition to human-readable messages.
为了解决这个问题,我们在错误对象中添加了标准错误代码,客户端可以使用它们以编程方式识别错误。 这是受Stripe的REST API如何返回字符串错误代码以及人类可读消息的启发。
We decided on three error codes to start: authentication_error
, resource_not_found
, and server_error
.
我们确定了要启动的三个错误代码: authentication_error
, resource_not_found
和server_error
。
To add these to our GraphQL responses, we passed our own formatError
function to express-graphql that maps exceptions thrown on the server to standard codes which get added to the response. The GraphQL spec generally discourages adding properties to error objects, but does allow for it by nesting those entries in a extensions
object.
为了将这些添加到我们的GraphQL响应中,我们将自己的formatError
函数传递给express-graphql,该函数将服务器上抛出的异常映射到添加到响应中的标准代码。 GraphQL规范通常不鼓励向错误对象添加属性 ,但是通过将这些条目嵌套在extensions
对象中来允许这样做。
Our GraphQL response errors were then easy to classify:
然后,我们的GraphQL响应错误易于分类:
While we developed our own way of adding codes to responses generated by express-graphql, apollo-server appears to offer similar built-in behavior.
虽然我们开发了自己的方法,将代码添加到express-graphql生成的响应中,但apollo服务器似乎提供了类似的内置行为 。
Once we figured out a good way of handling errors in our server, we turned our attention to the client.
一旦找到了处理服务器错误的好方法,我们便将注意力转向了客户端。
By default, we wanted our app to display a global error page (for example, a page with the message “oops something went wrong”) whenever we encountered a server_error
, authorization_error
, or authorization_not_found
. However, we also wanted the flexibility to be able to handle an error in a specific component if we wanted to.
默认情况下,当我们遇到server_error
, authorization_error
或authorization_not_found
时,我们希望我们的应用程序显示一个全局错误页面(例如,显示消息“糟糕的东西出错了”的页面)。 但是,我们还希望灵活性能够在需要时处理特定组件中的错误。
For example, if a user was typing something into a search bar and something went wrong, we wanted to display an error message in-context, rather than flash over to an error page.
例如,如果用户在搜索栏中键入某些内容而出现问题,则我们希望在上下文中显示错误消息,而不是闪过错误页面。
To achieve this, we first created a component called GraphqlErrorHandler
that would sit between apollo-client
’s Query
and Mutation
components and their children to be rendered out. This component checked for error codes in the response threw an exception if it identified a code we cared about:
为此,我们首先创建了一个称为GraphqlErrorHandler
的组件,该组件位于apollo-client
的Query
和Mutation
组件及其要渲染的子组件之间。 如果此组件标识了我们关心的代码,则在响应中检查错误代码会引发异常:
To use the GraphqlErrorHandler
, we wrapped apollo-client’s Query
and Mutation
components:
为了使用GraphqlErrorHandler
,我们包装了apollo-client的Query
和Mutation
组件:
Our feature component then used our own Query
component instead of directly accessing react-apollo
:
然后,我们的功能部件将使用我们自己的Query
部件,而不是直接访问react-apollo
:
Now that our React app was throwing exceptions when the server returned errors, we wanted to handle these exceptions and map them to the appropriate behavior.
现在,当服务器返回错误时,我们的React应用程序将引发异常,我们想要处理这些异常并将它们映射到适当的行为。
Remember from earlier that our goal was to default to displaying global error pages (for example, a page with the message “oops something went wrong”), but still have the flexibility to handle an error locally within any component if we desired.
请记住,从较早时起,我们的目标是默认显示全局错误页面(例如,显示消息“哎呀,出问题了”的页面),但如果需要,仍可以灵活地在任何组件中本地处理错误。
React error boundaries provide a fantastic way of doing this. Error boundaries are React components that can catch JavaScript errors anywhere in their child component tree so you can handle them with custom behavior.
React 错误边界提供了一种出色的方法。 错误边界是React组件,可以在其子组件树的任何位置捕获JavaScript错误,因此您可以使用自定义行为来处理它们。
We created an error boundary called GraphqlErrorBoundary
that would catch any server-related exceptions and display the appropriate error page:
我们创建了一个名为GraphqlErrorBoundary
的错误边界,该边界将捕获与服务器相关的所有异常并显示相应的错误页面:
We use the error boundary as a wrapper for all of our app’s components:
我们将错误边界用作所有应用程序组件的包装:
Error boundaries can be used deeper in the component tree if we want to handle errors in a component instead of rendering an error page.
如果我们要处理组件中的错误而不是呈现错误页面,则可以在组件树的更深处使用错误边界。
For example, here’s what it’d look if we wanted custom error handling behavior in our component from earlier:
例如,如果我们希望早些时候在组件中实现自定义错误处理行为,就会看到以下内容:
GraphQL is still relatively new, and error handling is a common challenge that developers seem to be running into. By using standardized error codes in our GraphQL responses, we can communicate errors to clients in a useful and intuitive way. In our React apps, error boundaries provide a great way to standardize our app’s error handling behavior while still having flexibility when we need it.
GraphQL仍然相对较新,错误处理是开发人员似乎遇到的常见挑战。 通过在GraphQL响应中使用标准化的错误代码,我们可以以有用和直观的方式将错误传达给客户。 在我们的React应用程序中,错误边界提供了一种很好的方式来标准化我们应用程序的错误处理行为,同时在需要时仍具有灵活性。
react 错误边界