【问题标题】:ReactJS: How to display an child component error in parent componentReactJS:如何在父组件中显示子组件错误
【发布时间】:2019-01-05 07:51:32
【问题描述】:

如果子元素发生错误,我想在我的父反应组件上显示错误消息。

在这种情况下,错误将是捕获 apollo 突变调用,例如您可以在 GrandChild 组件中看到的那样。

当然,我可以在父组件中创建一个函数,为错误设置一个状态值,并将该函数传递给每个孩子、孙子等等。 但是由于我的结构有点复杂,这意味着很多工作。这就是为什么我想到使用反应错误边界的原因。但这是正确的用例吗?

由于我使用的是nextJS,每个throw Error在开发模式下都会显示错误stacktrace,所以无法将错误显示为消息

Parent.js

export class Parent extends Component {
  render () {
    return (
      { /* if there is an error in any child component, it should be displayed here */
        this.props.error &&
        <Message>{error}</Message>
      }
      <Child {...props} />
    )
  }
}

GrandChild.js

class GrandChild extends Component {
  doAnything () {
    return this.props.assumeToFail({
      variables: { id: '123' }
    }).catch(error => {
      console.error(error) // <-- this error should be given back to parent
      throw new Error('fail') // <-- should I throw the error or call a custom function?
    })
  }

  render () {
    return (
      <Button onClick={this.doAnything().bind(this)}>anything</Button>
    )
  }
}

export default graphql(exampleMutation, { name: 'assumeToFail' })(GrandChild)

要在我的 nextJS 应用程序中使用错误边界,我只需添加

_app.js

class MyApp extends App {
  componentDidCatch (error, errorInfo) {
    console.log('CUSTOM ERROR HANDLING', error)
    // How do I get the error down to 'Component' in render()?
    super.componentDidCatch(error, errorInfo)
  }

  render () {
    const { Component, pageProps, apolloClient } = this.props
    return <Container>
      <ApolloProvider client={apolloClient}>
        <Component {...pageProps} />
      </ApolloProvider>
    </Container>
  }
}

到我的 _app.js 文件。但我不确定这是否是要走的路……而且我不知道如何将错误归结为Component

【问题讨论】:

  • @quirimmo 请查看更新后的帖子:我在 nextJS 应用程序中使用componentDidCatch,但这会导致始终在开发模式下显示堆栈跟踪,所以我无法显示组件中的错误。
  • 阅读我分享的链接。他们也谈论这个
  • @quirimmo 在 nextJS 中,stacktrace 不仅传递到控制台,而且还显示在屏幕上。因此,如果出现错误,应用程序将不再可见(在开发模式下)
  • componentDidCatch 只是其中的一部分,您还需要创建一个实现componentDidCatch 的错误边界组件,以便它可以返回一些错误状态并基于该返回一个回退组件。见reactjs.org/docs/error-boundaries.html。请注意,它确实会转储全屏堆栈跟踪“模态”,右上角有一个“X”可以关闭它并返回您的应用程序。

标签: javascript reactjs next.js


【解决方案1】:
  1. 实现这一点的最佳方法是使用反应状态管理,如 reduxfluxible。 如果您使用的是 react 状态管理,那么您可以通过从 child.js 发送消息来调用操作,并连接到 parent.js 中的 redux store 以轻松获取错误消息。

  2. 如果您决定使用您所描述的函数,您可以将一个函数传递给孩子,让孩子调用该函数。

Parent.js

export class Parent extends Component {
  state = {
    error: null,
  }

  render () {
    return (
      { /* if there is an error in any child component, it should be displayed here */
        this.state.error &&
        <Message>{this.state.error}</Message>
      }
      <Child
        {...props}
        defineError={(errMsg) => setState({ error: errMsg })}
      />
    )
  }
}

GrandChild.js

import PropTypes from 'prop-types';

class GrandChild extends Component {
  static propTypes = {
    defineError: PropTypes.func,    
  }

  doAnything () {
    return this.props.assumeToFail({
      variables: { id: '123' }
    }).catch(error => {
      this.props.defineError(error);
      console.error(error) // <-- this error should be given back to parent
      throw new Error('fail') // <-- should I throw the error or call a custom function?
    })
  }

  render () {
    return (
      <Button onClick={this.doAnything().bind(this)}>anything</Button>
    )
  }
}

export default graphql(exampleMutation, { name: 'assumeToFail' })(GrandChild)

【讨论】:

  • React 提供了一种默认方式来处理来自 any 渲染后代(不仅仅是直接子级)通过错误边界的错误,这也使您有机会更新任何 redux 或如果需要,通过生命周期函数使用应用程序状态。无需重新发明轮子。 React 的错误边界的工作方式类似于 try/catch 块,其中链上最近的边界(捕获)处理错误。
猜你喜欢
  • 1970-01-01
  • 2018-11-10
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多