Axios 从 Strapi.io BlogPosts 得到 slug 给出 404 - NextJS / Typescript

问题描述 投票:0回答:1

所以问题是我正在尝试呈现一个博客页面,侧面有 strapi 作为后端 cms。我有 [slug].tsx,它是检索页面数据的文件,该文件之前根据 .json 文件中列出的 slug 正确工作。

我现在正在尝试检索路径并发布数据,但我一直收到 404 错误并显示找不到该页面。 getStaticPaths / getStaticProps 函数如下所示:

export async function getStaticPaths() {
  try {
    const res = await axios.get(`http://localhost:1338/api/blogposts`);
    const data = res.data.data;
    const slugs = data.map((post: any) => post.attributes.slug);
    const paths = slugs.map((slug: string) => ({
      params: { slug },
    }));

    return { paths, fallback: false };
  } catch (error) {
    console.log(error);
    return { paths: [], fallback: false };
  }
}
export async function getStaticProps({ params }: any) {
  const slug = params.slug;

  try {
    const res = await axios.get(
      `http://localhost:1338/api/blogposts?slug=${slug}&_limit=1&populate=*`
    );
    const data = res.data;
    const filteredData = data.data.filter(
      (item: any) => item.attributes.slug === slug
    );
    if (filteredData.length > 0) {
      const post = filteredData[0].attributes;
      return { props: { post } };
    } else {
      return {
        notFound: true,
      };
    }
  } catch (error) {
    console.log(error);
    return {
      notFound: true,
    };
  }
}

它使用的 json 是 strapi.io cms localhost:1338/api/blogposts 返回以下数据:

{"data":[{"id":1,"attributes":{"title":"Use Case: Freeday launches its new ChatGPT-3.5 powered webchat","slug":"free-launched-chatgpt-3-5-powered-webchat","content":"# Test\nCustomer Care Agents within eCommerce spent a significant part of their time on customer contact to organize scheduling a return. The average response time is often too long to meet expectations of customers, resulting in a decreased user experience. Both impact the revenue of webshop businesses in the short and long term. Customers increasingly expect to handle their interactions via various channels. Interaction via whatsapp particularly, makes a shopping experience more personalized.\n\n## Test2\nAt Freeday we aim to unlock human potential. We automate repetitive work by applying a combination of logic and AI. This results in a digital employee that you drop into your existing processes. We all have a common mission to combat burn- and bore out, labor shortages and to fight to give everybody a Free Friday. Against this background, we felt that it was time to develop our technology even further.\n\n\n### Test3\nHumans have a few distinct capabilities that computers lack. When talking to a computer it typically provides pre-programmed answers to a single question, it has no regard for history, and it takes a lot of time to configure and maintain. Chances are high that you have heard about ChatGPT in the past few months. We have been working to be able to use this generative AI to capture any text source, such as a FAQ, and convert this to an answer to your questions.\n\nOften, we have noticed that large language models don’t know everything about current events. Therefore, we have been developing this new technology so our FAQ circumference this by injecting the right knowledge at the right time into the large language model. Then, we use our tuned prompts to make sure we don’t make up new information, and the tone of voice matches the company whom the digital employee is working for. \n\n![freeday-launches-chatgpt-webchat.jpg](https://res.cloudinary.com/dvxuf5kt7/image/upload/v1678436589/freeday_launches_chatgpt_webchat_090f50c8bc.jpg)\n\n#### Request returns chat assistant\nThe beauty is in the answers. Our technology can recognize and handle multiple questions in a single prompt. It finds the answers by looking in the knowledge base. While the knowledge base contains very lengthy answers and is not specific to the questions we ask, our digital employees can use that knowledge to generate answers that tackle all the questions that are in your prompt. We can tune our digital employees to be more, or less creative in answering either ‘I don’t know’ or a negative answer when something is not in the knowledge base. \n\n- List with some bulletpoints\n- and some more\n- and some more to test\n\nDon’t just take our word for it, we have dozens of satisfied customers who have already benefited from our AI-powered digital employees. Research shows that customers who experience longer waiting times are 18% less satisfied.\n\nIf you're interested in improving your customer service, then contact us for more information or a live demo. In fact, we've created a WhatsApp demo using our own FAQ text, but our digital employees can interpret any data set. So why wait? Start providing your customers with the best customer experience possible with [Freeday](/).","createdAt":"2023-03-09T12:45:48.114Z","updatedAt":"2023-03-10T09:02:55.843Z","publishedAt":"2023-03-09T14:32:31.639Z","intro_content":"We proudly introduce a new skill for our digital employees; ChatGPT-3.5 powered webchat. Through a combination of generative ai and logic, they interpret questions way better and generate answers that can even tackle multiple questions at once, based on a specific data set of our clients. Like for instance a knowledge base. The newly developed technique will be directly available to our clients.","url":null}},{"id":2,"attributes":{"title":"Menu Get Freeday Use Case: Check delivery status via chat","slug":"use-case-check-delivery-status-via-chat","content":"## The Challenge ##\nThe needs and desires of customers are changing fast. They expect speed, direct interaction, convenience and the option to choose via which channel they communicate with brands and services. Many companies find it hard to develop their services towards these preferred channels. Often due to packed IT backlogs.\n\n## The Solution: Check delivery status via chat\nCustomers can check its delivery status via selected channels directly with their mobile phone. As Freeday trains a digital assistant to perform the task, companies do not need to block precious IT resources to make steps forward into delivering customer happiness and convenience. For delivery services this is also an important asset towards their clients, for instance ecommerce platforms and webshops. Additionally Jennifer can also push notifications via preferred channels to keep customers informed. This way expectations are not only met, they are outperformed.\n\n## The Results\nCustomers are happier and feel recognized and in control of their way of checking their delivery statuses. While Jennifer, the digital assistant of Freeday, handles all these questions and tickets saving hundreds of hours of work, the contact center agents can deliver value to customers on the more complex questions via phone or live chat.\n\n### Check delivery status by chat\nJennifer improves the customer experience and saves time for contact centers\n\n### Integrations:\nMicrosoft Dynamics – Salesforce – Whatsapp – Microsoft Teams – Whatsapp – Zendesk – Genesys\n\nBelow you can find a demonstration of a WhatsApp interaction between a digital employee and a customer about the delivery status of a package. The video can be watched best in full screen.","createdAt":"2023-03-10T08:13:05.027Z","updatedAt":"2023-03-10T08:40:02.087Z","publishedAt":"2023-03-10T08:13:06.676Z","intro_content":"A chat service (multi channel options) with Freeday’s digital employee Jennifer to check delivery status via chat of mobile app services like Whatsapp, Telegram and Messenger. It brings more convenience for customers as they can choose their preferred channel to interact with a delivery service.","url":null}},{"id":3,"attributes":{"title":"aaa","slug":"kan-gewoon","content":"test","createdAt":"2023-03-10T09:51:21.516Z","updatedAt":"2023-03-10T10:55:45.346Z","publishedAt":"2023-03-10T09:51:38.872Z","intro_content":"test","url":"kan-gewoon"}},{"id":4,"attributes":{"title":"123","slug":"content","content":"te**st**","createdAt":"2023-03-10T10:56:55.732Z","updatedAt":"2023-03-10T11:03:15.668Z","publishedAt":"2023-03-10T10:56:56.599Z","intro_content":"test","url":"content2"}}],"meta":{"pagination":{"page":1,"pageSize":25,"pageCount":1,"total":4}}}

提前致谢。 编辑:完整代码如下所示:

import type { ReactNode } from "react";
import ReactMarkdown from "react-markdown";

import "@tailwindcss/typography";
import { useState, useEffect } from "react";
import Layout from "@/layouts/DefaultLayout";
import Newsletter from "@/components/sections/NewsLetterSection";
import ContentHeaderWide from "@/components/sections/PageHeaderWideSection";
import BlogListSection from "@/components/sections/article/BlogListSection";
import ArticleContentSection from "@/components/sections/article/ArticleContentSection";
import Head from "next/head";
import GenerateMetaTags from "@/utils/GenerateMetaTags";
import { gtmVirtualPageView } from "@/utils/GoogleTracking";
import router from "next/router";

import axios from "axios";

function Post({ post }: any) {
  const slug = post.slug;
  console.log(slug);
  const url = `http://localhost:1338/api/blogposts/?slug=${slug}&_limit=1&populate=*`;
  console.log(slug);

  const [blogPost, setContent] = useState({
    seo: { title: "", description: "" },
    slug: "",
    title: "",
    intro: "",
    content: "",
    video: "",
    thumbnail: "",
  });
  useEffect(() => {
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        const filteredData = data.data.filter(
          (item: any) => item.attributes.slug === slug
        );
        if (filteredData.length > 0) {
          setContent({
            seo: {
              title: filteredData[0].attributes.seo.title,
              description: filteredData[0].attributes.seo.description,
            },
            slug: filteredData[0].attributes.slug,
            title: filteredData[0].attributes.title,
            intro: filteredData[0].attributes.intro_content,
            content: filteredData[0].attributes.content,
            video: "",
            thumbnail:
              filteredData[0].attributes.thumbnail.data[0].attributes.name,
          });
          console.log(filteredData[0].attributes);
        } else {
          console.error(`No data found with slug 'test'`);
        }
      })
      .catch((error) => {
        console.error(error);
      });
  }, [url, slug]);

  useEffect(() => {
    const mainDataLayer = {
      pageTypeName: post.title || null,
      url: router.pathname,
    };
    gtmVirtualPageView(mainDataLayer);
  }, [post]);

  return (
    <>
      <Head>{GenerateMetaTags(blogPost.seo)}</Head>
      <ContentHeaderWide
        title={blogPost.title}
        slug={blogPost.slug}
        content={blogPost.intro}
        type="Blog"
      />
      <ArticleContentSection
        articles={post.articles}
        content={<ReactMarkdown>{blogPost.content}</ReactMarkdown>}
      />
      <BlogListSection />
      <Newsletter />
    </>
  );
}

Post.getLayout = (page: ReactNode) => (
  <Layout layoutColor={false}>{page}</Layout>
);

export async function getStaticPaths() {
  try {
    const res = await axios.get(`http://localhost:1338/api/blogposts`);
    const data = res.data.data;
    const slugs = data.map((post: any) => post.attributes.slug);
    const paths = slugs.map((slug: string) => ({
      params: { slug },
    }));

    return { paths, fallback: false };
  } catch (error) {
    console.log(error);
    return { paths: [], fallback: false };
  }
}
export async function getStaticProps({ params }: any) {
  const slug = params.slug;

  try {
    const res = await axios.get(
      `http://localhost:1338/api/blogposts?slug=${slug}&_limit=1&populate=*`
    );
    const data = res.data;
    const filteredData = data.data.filter(
      (item: any) => item.attributes.slug === slug
    );
    if (filteredData.length > 0) {
      const post = filteredData[0].attributes;
      return { props: { post } };
    } else {
      return {
        notFound: true,
      };
    }
  } catch (error) {
    console.log(error);
    return {
      notFound: true,
    };
  }
}

export default Post;

错误:

AxiosError: connect ECONNREFUSED ::1:1338
    at AxiosError.from (file:///Users/kevinuiterste/Desktop/freeday/website/node_modules/axios/lib/core/AxiosError.js:89:14)
    at RedirectableRequest.handleRequestError (file:///Users/kevinuiterste/Desktop/freeday/website/node_modules/axios/lib/adapters/http.js:577:25)
    at RedirectableRequest.emit (node:events:513:28)
    at eventHandlers.<computed> (/Users/kevinuiterste/Desktop/freeday/website/node_modules/follow-redirects/index.js:14:24)
    at ClientRequest.emit (node:events:513:28)
    at Socket.socketErrorListener (node:_http_client:494:9)
    at Socket.emit (node:events:513:28)
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  port: 1338,
  address: '::1',
  syscall: 'connect',
  code: 'ECONNREFUSED',
  errno: -61,
  config: {
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    adapter: [ 'xhr', 'http' ],
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    env: { FormData: [Function], Blob: [class Blob] },
    validateStatus: [Function: validateStatus],
    headers: AxiosHeaders {
      Accept: 'application/json, text/plain, */*',
      'User-Agent': 'axios/1.3.4',
      'Accept-Encoding': 'gzip, compress, deflate, br'
    },
    method: 'get',
    url: 'http://localhost:1338/api/blogposts',
    data: undefined
  },
  request: <ref *1> Writable {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: false,
      needDrain: false,
      ending: false,
      ended: false,
      finished: false,
      destroyed: false,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,
      corked: 0,
      sync: true,
      bufferProcessing: false,
      onwrite: [Function: bound onwrite],
      writecb: null,
      writelen: 0,
      afterWriteTickInfo: null,
      buffered: [],
      bufferedIndex: 0,
      allBuffers: true,
      allNoop: true,
      pendingcb: 0,
      constructed: true,
      prefinished: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: true,
      errored: null,
      closed: false,
      closeEmitted: false,
      [Symbol(kOnFinished)]: []
    },
    _events: [Object: null prototype] {
      response: [Function: handleResponse],
      error: [Function: handleRequestError],
      socket: [Function: handleRequestSocket]
    },
    _eventsCount: 3,
    _maxListeners: undefined,
    _options: {
      maxRedirects: 21,
      maxBodyLength: Infinity,
      protocol: 'http:',
      path: '/api/blogposts',
      method: 'GET',
      headers: [Object: null prototype],
      agents: [Object],
      auth: undefined,
      beforeRedirect: [Function: dispatchBeforeRedirect],
      beforeRedirects: [Object],
      hostname: 'localhost',
      port: '1338',
      agent: undefined,
      nativeProtocols: [Object],
      pathname: '/api/blogposts'
    },
    _ended: true,
    _ending: true,
    _redirectCount: 0,
    _redirects: [],
    _requestBodyLength: 0,
    _requestBodyBuffers: [],
    _onNativeResponse: [Function (anonymous)],
    _currentRequest: ClientRequest {
      _events: [Object: null prototype],
      _eventsCount: 7,
      _maxListeners: undefined,
      outputData: [],
      outputSize: 0,
      writable: true,
      destroyed: false,
      _last: true,
      chunkedEncoding: false,
      shouldKeepAlive: false,
      maxRequestsOnConnectionReached: false,
      _defaultKeepAlive: true,
      useChunkedEncodingByDefault: false,
      sendDate: false,
      _removedConnection: false,
      _removedContLen: false,
      _removedTE: false,
      strictContentLength: false,
      _contentLength: 0,
      _hasBody: true,
      _trailer: '',
      finished: true,
      _headerSent: true,
      _closed: false,
      socket: [Socket],
      _header: 'GET /api/blogposts HTTP/1.1\r\n' +
        'Accept: application/json, text/plain, */*\r\n' +
        'User-Agent: axios/1.3.4\r\n' +
        'Accept-Encoding: gzip, compress, deflate, br\r\n' +
        'Host: localhost:1338\r\n' +
        'Connection: close\r\n' +
        '\r\n',
      _keepAliveTimeout: 0,
      _onPendingData: [Function: nop],
      agent: [Agent],
      socketPath: undefined,
      method: 'GET',
      maxHeaderSize: undefined,
      insecureHTTPParser: undefined,
      path: '/api/blogposts',
      _ended: false,
      res: null,
      aborted: false,
      timeoutCb: null,
      upgradeOrConnect: false,
      parser: null,
      maxHeadersCount: null,
      reusedSocket: false,
      host: 'localhost',
      protocol: 'http:',
      _redirectable: [Circular *1],
      [Symbol(kCapture)]: false,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(kEndCalled)]: true,
      [Symbol(kNeedDrain)]: false,
      [Symbol(corked)]: 0,
      [Symbol(kOutHeaders)]: [Object: null prototype],
      [Symbol(kUniqueHeaders)]: null
    },
    _currentUrl: 'http://localhost:1338/api/blogposts',
    [Symbol(kCapture)]: false
  },
  cause: Error: connect ECONNREFUSED ::1:1338
      at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16) {
    errno: -61,
    code: 'ECONNREFUSED',
    syscall: 'connect',
    address: '::1',
    port: 1338
  }
}
enter code here
typescript next.js axios strapi slug
1个回答
0
投票

答案很简单.. 必须将本地主机的 url 更改为本地主机的真实 ip:localhost:1338 到 127.0.0.1:1338 现在可以了。太棒了!

© www.soinside.com 2019 - 2024. All rights reserved.