Check if Sanity post exists in React Router v5/v6 before rendering
const App = () => { return (
<BrowserRouter>
<Routes>
<Route element={<AllPosts />} path="/" exact /><Route element={<BlogSinglePost />} path="/blog/:slug" /><Route element={<NotFound />} path="*" /></Routes>
</BrowserRouter>
);
};
The issue you're experiencing is that your BlogSinglePost component needs to check if the document exists and handle the case when it doesn't. React Router will always match the /blog/:slug route before the * wildcard route, so you need to handle the 404 logic inside your BlogSinglePost component itself.
Here's how to fix this:
In your BlogSinglePost component:
import { useParams, Navigate } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { client } from './sanityClient'; // your Sanity client
const BlogSinglePost = () => {
const { slug } = useParams();
const [post, setPost] = useState(null);
const [loading, setLoading] = useState(true);
const [notFound, setNotFound] = useState(false);
useEffect(() => {
const query = `*[_type == "post" && slug.current == $slug][0]`;
client.fetch(query, { slug })
.then((data) => {
if (!data) {
setNotFound(true);
} else {
setPost(data);
}
setLoading(false);
})
.catch((error) => {
console.error('Error fetching post:', error);
setNotFound(true);
setLoading(false);
});
}, [slug]);
if (loading) return <div>Loading...</div>;
if (notFound) return <Navigate to="/404" replace />;
return (
<div>
{/* Your post content */}
<h1>{post.title}</h1>
{/* ... */}
</div>
);
};Update your routes:
const App = () => {
return (
<BrowserRouter>
<Routes>
<Route element={<AllPosts />} path="/" exact />
<Route element={<BlogSinglePost />} path="/blog/:slug" />
<Route element={<NotFound />} path="/404" />
<Route element={<NotFound />} path="*" />
</Routes>
</BrowserRouter>
);
};Key points:
- The GROQ query with parameters
*[_type == "post" && slug.current == $slug][0]filters documents by type and slug, using parameters for safe value passing - The
[0]at the end returns only the first match (ornullif no match exists) - When client.fetch returns
null, you know the document doesn't exist - Use React Router's
<Navigate>component to redirect to your NotFound route when the post doesn't exist - The wildcard
*route will catch any other unmatched routes
This approach ensures that the document existence check happens at the data-fetching level, which is where it needs to be since React Router doesn't know anything about your Sanity content.
Show original thread7 replies
Was this answer helpful?
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.