简体   繁体   中英

Next.js ISR page not being deleted after deleting it in CMS

I am trying out Next.js and build a small app which fetches posts from a headless WordPress app with GraphQL installed. Then I use Apollo/Client to get GraphQL content:

apollo-client.js

import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
  uri: process.env.WORDPRESS_GRAPHQL_ENDPOINT,
  cache: new InMemoryCache(),
});

export default client;

In index I grab the posts:

index.js

import Head from "next/head";
import styles from "../styles/Home.module.css";

import { gql } from "@apollo/client";
import Link from "next/link";
import client from "../apollo-client";

function Home(props) {
  const { posts } = props;
  return (
    <div className={styles.container}>
      <Head>
        <title>Wordpress blog posts</title>
        <meta
          name="description"
          content="Wordpress blog posts with Apollo Client"
        />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>=
        <div className={styles.grid}>
          {posts.map((post) => (
            <a
              key={post.node.databaseId}
              href={`/blog/${post.node.slug}`}
              className={styles.card}
            >
              <h2>{post.node.title}</h2>
              <div dangerouslySetInnerHTML={{ __html: post.node.excerpt }} />
            </a>
          ))}
        </div>
      </main>
    </div>
  );
}

export async function getStaticProps() {
  const { data } = await client.query({
    query: gql`
      query Posts {
        posts {
          edges {
            node {
              title
              databaseId
              slug
              excerpt(format: RENDERED)
            }
          }
        }
      }
    `,
  });

  if (data.posts.edges === 0) {
    return { notFound: true };
  }

  return {
    props: {
      posts: data.posts.edges,
    },
    revalidate: 10,
  };
}

export default Home;

Then for the single post page:

/blog/[slug].js

import Link from "next/link";
import { gql } from "@apollo/client";
import client from "../../apollo-client";

export default function BlogPage(props) {
  const { post } = props;

  if (!post) {
    return <p>Loading...</p>;
  }

  return (
    <div>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
      <Link href="/">
        <a>&larr; back to home</a>
      </Link>
    </div>
  );
}

export async function getStaticProps({ params }) {
  const { slug } = params;
  const result = await client.query({
    query: gql`
      query GetWordPressPostBySlug($id: ID!) {
        post(id: $id, idType: SLUG) {
          title
          content
        }
      }
    `,
    variables: { id: slug },
  });

  if (!result.data.post) {
    return { notFound: true };
  }

  return {
    props: {
      post: result.data.post,
    },
    revalidate: 10,
  };
}

export async function getStaticPaths() {
  const result = await client.query({
    query: gql`
      query GetWordPressPosts {
        posts {
          nodes {
            slug
          }
        }
      }
    `,
  });

  return {
    paths: result.data.posts.nodes.map(({ slug }) => {
      return {
        params: { slug },
      };
    }),
    fallback: true,
  };
}

When adding a new post it works, once I delete it, it does not get removed. This happens both when doing npm run dev and npm run build then npm start

I might be getting something wrong here in how ISR and revalidate works. Or I might be missing something in my code? Any help would be appreciated.

-- edit --

Meanwhile there are a couple of more threads, here on Stackoverflow and the Next.js github repository, related to what I'm experiencing. Related pages:

Next.js does not delete dynamic page deleted in CMS

https://github.com/vercel/next.js/issues/25470

Next.js ISR page not being deleted after deleting it in CMS

How to clear NextJs GetStaticPaths cache / "unpublish" a dynamic route?

https://github.com/vercel/next.js/discussions/18967

I am not sure if this matches your use-case, but in one of the projects I worked on, if the source data is deleted, we return a 404.

export async function getStaticPaths() {
  // Get the paths we want to pre-render based on posts
  // We do not need to generate anything during build
  return {
    paths: [],
    fallback: true,
  };
}

export async function getStaticProps({ params: { slug } }) {
  // Run your data fetching code here
  try {
    const data = await getData(slug);
    return {
      props: { data, slug },
      revalidate: 30,
      notFound: !data,
    };
  } catch (e) {
    return {
      props: { data: null, slug },
      revalidate: 30,
      notFound: true,
    };
  }
}

Docs: https://nextjs.org/blog/next-10#redirect-and-notfound-support-for-getstaticprops--getserversideprops

I think the problem is the fallback: true . You can find it in NextJS docs. In order to receive a 404 when you navigate to the deleted route you have to specify fallback: blocking

When using dynamic routes there are to ways to handle those paths that aren't in the getStaticPaths array. blocking or true .

The difference is that the first one works like getServerSideProps , so it's gonna fetch the data in the server, it will generate the HTML in the server an then return it, in future request it will serve the already static version of the page. This is the way you want to use if you want to return a 404 status code for those routes that were deleted.

Fallback: true works different. It serves a static version of the page, but you have to prepare that page to have a loader spinner or skeleton while fetch the data. If you prepare the page to do that, it will not return the 404 page even if you have a condition in your getStaticProps functions that return that. Actually, if you return only the notFound: true property, your page will throw an error because it's waiting for the props that will never come because it's returning only the notFound .

If you change the fallback: blocking , with run like getServerSideProps , will try to fetch the data, it will no exists because you previously deleted it, will return the notFound: true and with that the 404 page error. If you use fallback true it will try to serve the static page and then fetch the data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM