Home > OS >  update State is not triggering render in React 18
update State is not triggering render in React 18

Time:12-29

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'
    )}
  </>
);
  • Related