如何处理React / Typescript中的REST API错误?

时间:2019-11-19 05:54:53

标签: reactjs typescript axios

我上周参加了为期两天的React培训班。讲师试图将长达数周的信息浪费到两天之内。我们在“类”中打了个粗略的二十一点游戏(或者就是Class<T>: => () await (...p)那里有一点Typescript笑话。)该类没有解决如何访问REST API的问题。所以在这里,我陷入了一堆令人困惑的无法理解的代码中,我什至不确定是React还是Typescript。任何人,这是我的App.tsx文件:

import React, {useState} from 'react';
import './App.css';
import {fetchUser, User, UserCtx} from "./User";
import {useAsync} from "./ss-react-utils";

const AppLoaded = ({user}: {user: User}) => {
  return <div className="App">
    {user.userName}
  </div>;
};

const AppLoading = () => {
  return <div>Loading ...</div>;
};

const App: React.FC = () => {  // I guess the FC stands for F*king Confusing 
  const [user, setUser] = useState<User | null>(null);

  useAsync({
    op: fetchUser,
    onSuccess: setUser,
    deps: []
  });

  if (user !== null) {
    return <AppLoaded user={user} />;
  } else {
    return <AppLoading/>;
  }
}

export default App;

这是ss-react-utils.tsx文件:

import React, {CSSProperties, DependencyList, useEffect} from "react";

export type Op<T> = () => Promise<T>;
export type OnSuccess<T> = (data: T) => void;

export function useAsync<T>({op, onSuccess, deps}: { op: Op<T>, onSuccess: OnSuccess<T>, deps?: DependencyList }) {

    useEffect(() => {
        const doOp = async () => {
            const data: T = await op();
            onSuccess(data);
        };
        doOp();

        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, deps);
}

... some other unrelated ( I think ) code ...

当我运行该代码时,我得到了... enter image description here

如果REST API返回403禁止的错误,我想知道如何处理该错误并向用户显示登录页面。

是的,我知道REST API返回403错误。因此,请不要使用you are getting a 403 error.来回答问题:)

我已经看到很多回答,说使用componentDidMount,但是讲师说那是做React的老方法,他打算去教钩子。在我完全放弃编写React的“新”方法之前,我想尝试一下讲师的工作。可能一起反应。所以请帮忙:)

更新:我正在使用Django Rest Framework,它的行为符合预期。 enter image description here

3 个答案:

答案 0 :(得分:0)

在我的上一个项目中,我从api异步下载数据时遇到问题。然后我必须使用这样的东西:

componentDidMount() {
fetch("API")
  .then(res => res.json())
  .then(json => {
    ...
    this.setState({ data });
  });
}

但是此代码用于类组件。您可以仅获取数据来测试相同的代码吗?

我们将以这种方式排除是否是数据下载本身的问题。

答案 1 :(得分:0)

您可以通过这种方式处理错误。这是示例:-

componentDidMount() {
    fetch(URL)
      .then(results => results.json())
      .then(data => this.setState({ results: data }))
      .catch(error=>{   //here you can handel errors
          if(error.response){
              alert("Error occurred"); 
          }
      });
  }

答案 2 :(得分:0)

const App: React.FC<{id}> = ({id}) => {
  const op = useCallback(()=> fetchUser(id), [id]);
  const { data: user, loading, error } = useFetch(op);
  useEffect(()=> {
     if (!error){return}
     alert(error); // if wanna alert error;
  }, [error]);
  return (
    <>
      {loading && <AppLoading />}
      {user && <AppLoaded user={user}/>}
      {error && <pre>{error.message | error}</pre>}
    </>
  )
}
function useFetch<T>(op: ()=> Promise<T>){
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<T | null | undefined>();
  const [error, setError] = useState<string | null>(null);
  const id = useRef(0);
  useEffect(()=> ()=> {
    // on unmount
    id.current = 0;
  }, []);
  useEffect(()=> {
     const currentID = ++id.current;
     setLoading(true);
     op().then((data)=> {
       // ignore when query changed
       if (id.current !== currentID) { return; }
       setData(data);
       setLoading(false);
       setError(null);
     }, (err)=> {
       if (id.current !== currentID) { return; }
       setError(err.message || err);
       setLoading(false);
     })
  }, op);
  return {data, loading, error}
}