I have a very simple component that fetches data and then shows it.
Here is the code
const SinglePost = (props) => {
const [post, setPost] = useState({})
const token = useContext(AuthStateContext).token
const url = process.env.REACT_APP_BASE_API_URL
const path = "/api/blog/post/"
const { id } = useParams()
const getPost = async (postId) => {
try{
const response = await axios.get(url path postId, {
headers: { "Authorization": "Bearer " token }
})
setPost(response.data.post)
}catch (error){
console.log(error)
}
}
//get the post
useEffect(() => {
getPost(id).catch(error => console.log(error))
}, [])
return (
<>
{
post.length > 0 ?
<article className="blog-post">
<h2 className="blog-post-title mb-1">{post.title}</h2>
<p className="blog-post-meta">{moment(post.created_at).fromNow()} by <a
href="#">{post.author.name}</a></p>
<p>{post.content}</p>
</article>
:
"Loading Content"
}
</>
)
}
export default SinglePost
In useEffect
I am passing empty array []
to make sure that it runs only once after the render. In useEffect I am fetching the data and updating the state
setPost(response.data.post)
Ideally, when state is updated, component re-renders. But in this case I only see
Loading Content
string on the screen. If I remove []
from useEffect, it causes an infinite loop. What did i do wrong here?
CodePudding user response:
Your render condition was wrong here
post.length > 0
You can fix it like this
const [post, setPost] = useState();
...
return (
<>
{post ? (
<article className="blog-post">
<h2 className="blog-post-title mb-1">{post.title}</h2>
<p className="blog-post-meta">
{moment(post.created_at).fromNow()} by
<a href="#">{post.author.name}</a>
</p>
<p>{post.content}</p>
</article>
) : (
'Loading Content'
)}
</>
);