所以基本上我等待身份验证从 aws amplify/cognito 返回当前经过身份验证的用户,然后我运行一个查询来获取他们的数据(我故意让它出错,这样我就可以检查这里错误边界的功能)情况)。我在 app.tsx 中导入 client.ts 并调用 getData 函数,将参数传递给它,然后将 axios 错误对象返回给调用函数。我遇到了一些问题,但无法让其中任何一个问题正常工作,如下所述:
- 如果我在 data[0].error 条件中设置“抛出”,它会给出 我没有捕获 Promise,因为我没有拒绝()其中的 Promise 手动。当我尝试这样做时,我收到一些 typescript 错误 无法做到这一点,因为组件没有该类型 某事或其他(我将重做并发布实际错误)
2) 如果我使用条件在渲染函数中设置 throw 基于 state.hasError,它可以工作并达到错误边界,但是 然后抛出一个错误,因为我有一个未捕获的异常,因为我 我没有发现我抛出的错误
如果我发现渲染函数中抛出的错误,它 到达错误边界,但随后提示 render() 不是 返回任何内容
因此,寻求有关如何从设计角度改进这一点的建议 我在这方面找到的所有示例遇到的问题是,它们都是简单的示例,其中异步调用是直接在组件中进行的,而错误是直接在组件中处理的,而我不想真正这样做,因为当我可以简单地将代码传递给驻留在一个位置的函数来返回我想要的内容时,我喜欢不必一遍又一遍地重复代码。
应用程序.tsx:
async componentDidMount() {
await Auth.currentAuthenticatedUser().then( data => {
this.onGetAuthUser(data.username);
var username = data.username;
//rockset query --need to implement error handling elsewhere
getData('select * from "ruzzleLeagueCollection" WHERE username=:username',
[{"name": "username",
"type": "string",
"value": data.username}]).then((data: any) => {
if(data[0] != null) {
if(data[0].error != null) {
this.setState({error: true, errorData: data[0].error});
return;
}else {
//get the logged in user.
this.onGetLoggedUser(data[0]);
}
}else {
//create the loggedUser object and pass it
this.onGetLoggedUser([{
username: username,
ruzzleName: null,
group: 0,
hasProfile: false,
currentSkill: null,
highestSkill: null
}])
}
});
});
}
render() {
try{
if(this.state.error) throw this.state.errorData;
return (
<div >
<Router>
<div>
<NavBar/>
<Switch>
<Route exact path="/" component={Home}/>}/>
<Route path="/players" component={Players} />
<Route path="/season" component={Season} />
<Route path="/records" component={Records} />
<Route path="/stats" component={Stats}/>
<Route path="/admin" component={Admin}/>
</Switch>
</div>
</Router>
</div>
)
} catch(err) {
console.log('error caught!');
}
}
客户端.ts
import axios from 'axios';
const apiKey = 'fgf' //process.env.REACT_APP_ROCKSET_APIKEY;
const apiServer = process.env.REACT_APP_ROCKSET_APISERVER;
const url = apiServer + '/v1/orgs/self/queries';
const headers = { headers: {'Authorization': 'ApiKey ' + apiKey}};
var data = {'sql':{
'query': '',
'parameters': [
]}
}
//GET REQUEST
export async function getData(query: string, parameters: any) {
data.sql.query = query;
data.sql.parameters = parameters == null? undefined: parameters;
try {
const response = await axios.post(url, data, headers)
return response.data.results;
}catch(err) {
console.error('The following error occurred ' + err.message)
if(err.response) {
return handleErrors(err.response, 'response');
}else if(err.request) {
return handleErrors(err.request, 'request');
}else {
return handleErrors(err, 'other');
}
}
}
function handleErrors(error: any, errorType: string) {
switch(errorType) {
//this is a response error
case 'response':
return [{error: {
data: error.data,
status: error.status,
headers: error.headers
}
}]
case 'request':
return [{ error:
{ data: error.request}
}]
default:
return [{error: {
data: error.message}
}]
}
}
错误.tsx:
export class Errors extends Component<any,IState>{
constructor(props:any){
super(props);
this.state = {
hasError: false,
alertOpen: true,
error: null,
info: null
};
}
componentDidCatch(e: any, info: any) {
this.setState({
hasError: true,
error: e,
info: info
});
}
closeAlert() {
this.setState({alertopen: false, hasError: false})
}
//render the error screen
render() {
if(this.state.hasError){
var msg = 'Oops! Something went wrong. Error: ' + this.state.info.componentStack;
var title = 'Error in ' + this.state.error.data.message + ' ' + this.state.error.status;
return(
<div>
<React.Fragment>
<AlertDialogSlide
open={this.state.alertOpen}
title = {title}
message= {msg}
closeAlert={() => this.closeAlert()}
error={true}
>
</AlertDialogSlide>
</React.Fragment>
</div>
)
}
return this.props.children;
}
}
index.js(入口点)--错误边界环绕
ReactDOM.render(
<Provider store={store}>
<Errors>
<App />
</Errors>
</Provider>
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();
最佳答案
我在 https://medium.com/trabe/catching-asynchronous-errors-in-react-using-error-boundaries-5e8a5fd7b971 上发现了这个小技巧。
它对我有用,所以为什么不......
import { useCallback, useState } from "react";
/** A workaround for error boundary async limitations. */
export const useAsyncThrow = () => {
const [_, setErr] = useState();
return useCallback(
(e) =>
setErr(() => {
throw e;
}),
[setErr]
);
};
// Example:
// const asyncThrow = useAsyncThrow;
// (async () => asyncThrow(new Error()))();
关于reactjs - React 错误边界无法与异步函数正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56995736/