ReactJs component showing old data (which is not a list even)

Viewed 190
import { useState, useEffect } from "react";
import axios from "axios";
import { useParams } from "react-router-dom";

const Post = () => {
  const params = useParams();

  const [post, setPost] = useState(null);

  useEffect(() => {
    fetchPost();
  }, []);

  const fetchPost = () => {
    axios
      .get(
        `https://api.example/v1/json/post?post=${params.postSlug}`
      )
      .then((response) => {
        setPost(response.data.data.post);
      })
      .catch((error) => console.log({ error }));
  };

  return post ? (
    <div className="singlePost">
      <div className="content" key="content">{post.content}</div>
    </div>
  ) : null;
};

export default Post;

This is my whole component and API is developed on laravel. If I change the backend data from db React client does not pull in the new content while if I paste the endpoint in a browser or Postman, it does display updated content. I know that I can just add a timestamp at the end of url to force frontend to pull new data everytime but that'll effect the efficiency of application. Can someone explain the reason and solution to this issue without using any cache burst (i.e. timestamp in url or 'no-cache' in axios headers).

Thanks in advance

5 Answers

If you are sure data is updated in DB, your backend is working properly and you are refreshing your react app and still can't see the updated data, then we don't have enough information to solve your issue.

Are you sure you are making the same request from postman and from the react app? Did you try deleting cache from the browser?

One solution to debug this could be creating a button that calls your fetchPost method on click and see what happens

You can try to add params or postSlug as a useEffect() dependency.

Example:

const { postSlug } = useParams()

useEffect(() => {

    if(postSlug)
        fetchPost(postSlug)

}, [postSlug])

const fetchPost = (postSlug) => {

    axios
        .get(`https://api.example/v1/json/post?post=${postSlug}`)
        .then((response) => {
            setPost(response.data.data.post);
        })
        .catch((error) => console.log({ error }))

}

I'm not quite sure if it will work, but without the dependency, perhaps the fetchPost() is executing within the useEffect() using an empty slug. Hence, the cached response.

Make sure you got web inspector networks' cache disabled.

Make sure that the data you're receiving is exactly what you're accessing: response.data.data.post.data.data doesn't seem well. Make sure you receive an object and not an array, because you need to map your content if it is an array.

  1. If you want your backend to inform the front-end that "Hey! My data changed, so, pls, update!" you can use Laravel Broadcasting - https://laravel.com/docs/5.6/broadcasting .

  2. Since I do not have a react-app to test your code + typing on mobile, all I can suggest is to try adding the useEffect() dependency and then see if that works.

import { useState, useEffect } from "react";
import axios from "axios";
import { useParams } from "react-router-dom";

const Post = () => {
  const params = useParams();

  const [post, setPost] = useState(null);

  useEffect(() => {
    fetchPost();
  }, [post]); <------------- Add the dependency here
...

In any case, if Postman processes the API Endpoint properly, then the issue must be with your code.

I had one problem like that so i fixed it by adding a useEffect with param that will react as component did update, so once the data get changed in your case the post my state exists will be true then you will be able to render your jsx.

try this :

    import { useState, useEffect } from "react";
    import axios from "axios";
    import { useParams } from "react-router-dom";
    
    const Post = () => {
      const params = useParams();
    
 

     const [post, setPost] = useState(null);
/***************************************/
          const [exists, setExists] = useState(false);
    
    useEffect(() => {
    post ? setExists(true) : null
       //this exists will let you render your component once the poste state is changed 
      }, [post]);
/****************************************/
      useEffect(() => {
        fetchPost();
      }, []);
    
      const fetchPost = () => {
        axios
          .get(
            `https://api.example/v1/json/post?post=${params.postSlug}`
          )
          .then((response) => {
            setPost(response.data.data.post);
          })
          .catch((error) => console.log({ error }));
      };
    
      return exists ? (
        <div className="singlePost">
          <div className="content" key="content">{post.content}</div>
        </div>
      ) : null;
    };
    
    export default Post;
Related