Red Cricket
Red Cricket

Reputation: 10480

How to handle REST API errors in React/Typescript?

I took a two day React training class last week. The instructor tried to jam a weeks worth of info into two days. We slapped together a crude blackjack game in the "class" (or is that Class<T>: => () await (...p) ha ha little Typescript joke there.) The class did not get around to covering how to access a REST API. So here I am stuck with a bunch of confusing unreadable code that I am not even sure is React or Typescript. Any whooo this is my App.tsx file:

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;

Here's the ss-react-utils.tsx file:

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 ...

when I run that code I get this ... enter image description here

I would like to know how to handle the error and display the login page to the user if the REST API returns a 403 forbidden error.

And Yes I know the REST API is returning a 403 error. So please don't answer the question with you are getting a 403 error. :)

Also I have seen a lot of answers that say use componentDidMount but the instructor said that was the old way of doing React and he was going to teach about hooks instead. Well would like to try what the instructor was getting at before I completely give up on the "New" way to code React. And probably React all together. So please help :)

UPDATE: I am using Django Rest Framework and it is behaving as expected. enter image description here

Upvotes: 0

Views: 3294

Answers (3)

欧阳斌
欧阳斌

Reputation: 2351

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}
}

Upvotes: 1

Shashwat Prakash
Shashwat Prakash

Reputation: 484

You can handle error in this way. Here is the example:-

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"); 
          }
      });
  }

Upvotes: 0

kstepien
kstepien

Reputation: 1233

In my last project, I have a problem with async download data from api. Then I must use something like this:

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

But this code is for the class component. Can you test this same code with only fetch data?

We will exclude in this way whether it is the fault of the data download itself.

Upvotes: 0

Related Questions