axios NextJS/Strapi Dynamic Routing with bad slug返回空数据而不是404

vuktfyat  于 2023-10-18  发布在  iOS
关注(0)|答案(1)|浏览(134)

我正在Next.JS 13中设置动态路由(使用App Router方法),并在CMS中使用Strapi v4。
我通过Strapi内容类型中名为slug的字段过滤API请求,成功获取了内容类型work的数据。我遇到的问题是,当我转到一个在我的work内容类型中没有对应slug的URL时,比如:localhost:3000/works/asdf,页面加载并返回一个空的数据数组,而不是一个404页面,这是我希望它做的。
文件夹结构为:

app/
  ├── works/
  │   ├── page.js
  │   └── [slug]/
  │       └── page.js

以下是对我的内容类型work的调用返回的内容:

{
    "data": [
        {
            "id": 1,
            "attributes": {
                "title": "Test Work Item",
                "description": "Test work description",
                "createdAt": "2023-08-07T21:11:53.187Z",
                "updatedAt": "2023-08-07T21:12:45.925Z",
                "publishedAt": "2023-08-07T21:11:54.526Z",
                "slug": "test-work-item",
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pageSize": 25,
            "pageCount": 1,
            "total": 1
        }
    }
}

下面是相关的Next.JS代码

'use client'
import useSWR from 'swr';
import axios from 'axios';

const fetcher = (url) => axios.get(url).then((res) => res.data);

export default function SingleWork({ params }) {
    const { slug } = params;
    const { data, error } = useSWR(
        `http://localhost:1337/api/works?filters[slug][$eq]=${slug}&populate=*`,
        fetcher
    );

    if (error) return <div>Error loading data...</div>;
    if (!data) return <div>Loading...</div>;

    return (
        <div>My Post: {JSON.stringify(data)}</div>
    )
}
ercv8c1e

ercv8c1e1#

经过一番研究,这就是我的着陆点。这是可行的,尽管从技术上讲,这仍然不是“真实的”404错误,因为没有相应slug的查询仍然返回200。我想我需要重写strapi控制器来寻找slug而不是id。如果有人知道更好的方法,我会很感激。

**编辑:**我已经重写了Strapi控制器来寻找slug而不是id,现在当我在Postman中查询时,只有实际的slug返回200,其他所有的都返回404,但是在我的NextJS前端,所有的slug仍然可以解决。
前端

'use client'
import useSWR from 'swr';
import { useRouter } from 'next/navigation';

const fetcher = (url) => axios.get(url).then((res) => res.data.data);

export default function SingleWork({ params }) {
    const router = useRouter();
    const { slug } = params;
    const { data, error, isLoading } = useSWR(
        `http://localhost:1337/api/works?filters[slug][$eq]=${slug}&populate=*`,
        fetcher
    );

    if (error) {
        return (
            <div>failed to load</div>
        )
    }
    if (isLoading) {
        return (
            <div>Loading...</div>
        )
    };

    if (!data[0]) {
        router.push("/404")
    } else return (
        <div>My Post: {JSON.stringify(data)}</div>
    )
}

后台

module.exports = createCoreController('api::work.work', ({ strapi }) => ({
    async findOne(ctx) {
        const { id } = ctx.params;

        const entity = await strapi.db.query('api::work.work').findOne({
            where: { slug: id },
            populate: true
        })

        const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
        return this.transformResponse(sanitizedEntity);
    }
}));

相关问题