反应ErrorBoundary-只是无法正常工作

时间:2019-02-23 14:46:05

标签: javascript reactjs redux error-handling

抱歉,我知道有人问过这个问题,但是我找不到适合我的示例。似乎很难理解是否有这么多人为此苦苦挣扎。

我只需要知道如何以一种干净,简单的方式在React中捕获错误。我正在使用CRA 2.0 /反应16.7。我希望在操作级别尝试/捕获块,因为这是业务逻辑集中在我的应用程序中的地方。

我按说明阅读并实现了它,但是我的ErrorBoundary对象从不捕获错误。

示例:

import React, { Component } from "react";

class ErrorBoundary extends Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false };
    }

    static getDerivedStateFromError(error) {
        return { hasError: true };
    }

    componentDidCatch(error, info) {
        console.log("ErrorBoundary: ", error);
        console.log("ErrorBoundary: ", info);
    }

    render() {
        if (this.state.hasError) {
            return <h1>Something went wrong.</h1>;
        }
        return this.props.children;
    }
}

export default ErrorBoundary;

我将路线包裹在顶层:

    return (
        <BrowserRouter>
            <ErrorBoundary>
                <div className="main-container">
                    <SideBar />
                    <div className="some-class">
                        <Switch>
                            <Route path="/events" component={Events} />
                            <Route exact path="/" component={Index} />
                        </Switch>
                    </div>
                </div>
            </ErrorBoundary>
        </BrowserRouter>
    );

在上面的“事件”中,我进行了API调用,该调用在API端抛出了500错误:

componentDidMount() {
    this.props.getAllEvents();
}

这是Redux动作:

export const getAllEvents = () => {
    return async (dispatch, getState) => {
        try {
            let state = getState();
            const result = await get({
                state: state,
                route: "/v1/events"
            });
            dispatch({
                type: GET_EVENTS,
                payload: result
            });
        } catch (e) {
            console.log("Something went wrong at action...");
        }
    };
};

...“ get()”只是包装了Axios GET-没什么。

我从失败的API调用中看到控制台中的500错误。我从未在控制台中从上方的catch块看到“出了点问题...”,尽管在调试时该行确实被命中了。

“ componentDidCatch()”方法永远不会被调用-“ hasError”始终为false,并且始终呈现子级。

如果我在API端点中删除了throw块,则一切正常,并且我得到了数据。我只是无法在UI级别捕获错误。我已经尝试过在“ componentDidMount()”中进行try / catch,我尝试在动作中删除try / catch块...行为不会改变。

谢谢。

2 个答案:

答案 0 :(得分:2)

正如其他答案正确指出的那样,React错误边界只会捕获渲染错误。

由于您正在使用redux,因此可以针对诸如此类的情况构建自己的机制:

  1. 每当发生错误时,您就调度一个具有error属性的操作。
  2. Reducer仅查找具有error属性的动作。它接收操作并在状态树中更新“全局错误”状态
  3. 应用程序级connect封装的包装器组件会看到此状态更改并显示后备UI。

例如:
使用error属性发送操作:

export const getAllEvents = () => {
    return async (dispatch, getState) => {
        try {
            ...
        } catch (e) {
            dispatch({
                type: ERROR, 
                error: e // dispatch an action that has `error` property
            });
        }
    };
};

Reducer看到它并更新state.error部分:

export default function errorReducer(state = null, action) {
  const { type, error } = action;
  if (type === RESET_ERROR_MESSAGE) {  // an action to clear the error
    return null;
  } else if (error) { // any type of action, but contains an `error`
    return error;
  }
  return state;
}

现在,您将应用包装在connected边界中:

function Wrapper({error}) {
  if(error) return <h1>Something went wrong</h1>;
  return <App/>;
}

export default connect(
  state => ({
    error: state.error,
  })
)(Wrapper);

答案 1 :(得分:0)

来自React Error Boundaries docs

  

错误边界不能捕获以下错误:

     
      
  • 事件处理程序(learn more)
  •   
  • 异步代码(例如setTimeout或requestAnimationFrame回调)
  •   
  • 服务器端渲染
  •   
  • 错误边界本身(而不是其子级)引发的错误
  •