Reputation: 8783
I have used React 17
, MobX
and Typescript
in my project.
In postDetails.tsx file, I want to show the article but I got this error:
TypeError: Cannot read property 'Description' of undefined.
While the data is available, the status cannot be updated!
(I just found out that I did not receive the updated status. It means that I receive the last value of the state.)
How can I solve the problem?
If I comment this line of code, {/* <h1>{(postStore.postDetails.Description)}</h1> */}
, you can see the order of the execution line code. It's not correspondig to the order of line code!
import React, { useEffect } from "react";
import { useParams } from "react-router-dom";
import { observer } from "mobx-react-lite";
import { useStore } from "../../app/stores/store";
import "./postDetails.css";
import { runInAction, toJS } from "mobx";
export default observer(function PostDetails() {
const { postStore } = useStore();
let { id } = useParams<{ id?: string }>();
console.log("0001 - before useEffect");
useEffect(() => {
console.log("0002 - in useEffect");
try {
runInAction(async () => {
await postStore.details(id);
})
console.log("0003 - after executing postStore.details(id)");
console.log("postStore.selectedPost : ", toJS(postStore.selectedPost));
}
catch (error) { }
}, [id, postStore]);
console.log("0004 - right after the useEffect");
console.log("just befor return: ", postStore.postDetails);
return (
<>
{console.log("0005 - I expected first run useEffect for getting the data.")}
/* The data is not available */
{<h1>{(postStore.postDetails.Description)}</h1>}
</>
)
})
postStore.ts:
selectedPost: IPostModel | undefined = undefined;
details = async (id: string) => {
this.loadingInitial = true;
try {
const detailPost = await agent.Post.details(id);
runInAction(() => {
this.selectedPost = detailPost;
})
}
catch (error) {
console.log(error);
this.setLoadingInitial(false);
}
}
Upvotes: 0
Views: 756
Reputation: 18516
In addition to my comment: your code should be something like that:
export default observer(function PostDetails() {
const { postStore } = useStore();
let { id } = useParams<{ id?: string }>();
useEffect(() => {
postStore.details(id)
}, [id, postStore]);
if (!postStore.postDetails) {
return <div>Loading...</div>
}
return (
<h1>{(postStore.postDetails.Description)}</h1>
)
})
Just handle the case when details is not yet available.
Or you can add isLoading
flag to your store to make it more transparent what is going on.
Upvotes: 1