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