Why is caching not working while fetching Data on the Server with fetch?

78 views Asked by At

I have created a post listing application and upon clicking on each post the user will be redirected to single details page of the post

index.js (list of posts)

export default function Home(props) {
    const [postData, setPostData] = useState([]);

    useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts", { next: { revalidate: 10 } })
            .then((res) => res.json())
            .then((data) => {
                setPostData(data);
            });
    }, []);

    const cardArr = postData.map((post) => <Card data={post} key={post.id} />);

    return (
        <Layout>
            <Header>
                <div>Posts</div>
            </Header>
            {cardArr}
        </Layout>
    );
}

[id].js (single post detail page)

export const PostPage = (props) => {
    const router = useRouter();

    const [post, setPost] = useState({});

    useEffect(() => {
        fetch(`https://jsonplaceholder.typicode.com/posts/${router.query.id}`, {
            next: { revalidate: 1000 },
        })
            .then((res) => res.json())
            .then((data) => {
                setPost(data);
            });
    }, []);

    return (
        <Layout>
            <Header>
                <div className={styles.header}>{post.title}</div>
            </Header>
            <div>{post.body}</div>
        </Layout>
    );
};

export default PostPage;

I am trying to implement route caching. Such that if I go to one post then request is made to the server and the data will be cached. Next time if I go to same route within some time then instead of fetching data from the server it should display data from the cache.

I followed next js documentation where they used

{ next: { revalidate: 10 } }

But it is not working please guide me if I am missing something.

1

There are 1 answers

0
Fabio Nettis On

Looking at your code, you seem to mixing app-dir with pages-dir logic. In reality you are not fetching anything "on the server" but on the client, judging by the usage of useEffect and useState inside your components. As server components you would define it like this:

export default async function Home(props) {
  // See how the function is asynchronous and I directly fetch inside 
  // the function body, without any effect whatsoever.
  const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
    next: { revalidate: 10 },
  });

  const postData = await response.json();

  return (
    <Layout>
      <Header>
        <div>Posts</div>
      </Header>
      {postData.map((post) => (
        <Card key={post.id} data={post} />
      ))}
    </Layout>
  );
}

Furthermore I have noticed you seem to be using the router from next/router, that only works inside the pages directory. When using the app directory you would be importing it from next/navigation, and retrieve your query from the searchParams prop passed to every page.


I strongly recommend you take a look at the official documentation for the new app-router since you do not seem to understand the fundamentals at all.