Home > front end >  Trying to create an async function inside useEffect returning type error still
Trying to create an async function inside useEffect returning type error still

Time:12-08

I am trying to do a database call inside a useEffect() but make it async because currently it returns undefined momentarily before returning the database information. This results in an error:

Uncaught (in promise) Error: Error in retrieving book details. TypeError: Cannot read properties of undefined (reading 'info')

Here is my useEffect() call:

useEffect(() => {
    const getBookInfo = async () => {
      await services.bookData.getBookContent(bookID).then((res: BookContent) => {
        setContent({
          id: res.id,
          metadata: res.metadata,
          name: res.name,
          info: res.info,
          type: res.type,
        });
        console.log(content);
        dispatch(setBookContentThunk(content));
      });
    };
    getBookInfo().catch((err: any) => {
      throw new Error(`Error in retrieving book details. ${err}`);
    });
  }, [authState.status]);

It also results in some type errors in the IDE such as this at res.id:

(parameter) res: BookContent
Argument of type '{ id: string; metadata: MetaData; name: string; info: BookInfo[]; type: "book"; }' is not assignable to parameter of type 'SetStateAction<undefined>'.
  Object literal may only specify known properties, and 'id' does not exist in type '(prevState: undefined) => undefined'.ts(2345)

I'd be grateful for any pointers!

CodePudding user response:

One way is:

You can check for both undefined and the content Types that you are getting.

const [content, setContent] = useState<{...define your types here} | undefined>({});

The Second way is: Set the content only when the data is not undefined.

if(!!content){
    setContent({
        id: res.id,
        metadata: res.metadata,
        name: res.name,
        info: res.info,
        type: res.type,
    });
    console.log(content);
    dispatch(setBookContentThunk(content));
}

And you can use both simultaneously.

CodePudding user response:

in the useState, add a type to state variables. like this

  const [content, setContent] = useState<{ id: string; metadata: MetaData; name: string; info: BookInfo[]; type: "book"; }>()

In the useEffect check if data exist before assign to the setState

  services.bookData.getBookContent(bookID).then((res: BookContent) => {
        if(res){
         setContent({
           id: res.id,
           metadata: res.metadata,
           name: res.name,
           info: res.info,
           type: res.type,
         });
          console.log(content);
          dispatch(setBookContentThunk(content));
       }
      });
  • Related