nextjs 动态路由渲染内容不起作用

Ven*_*son 11 reactjs next.js

我被这个问题困了很多天。我正在使用Next.js并且有 3 页。

  • 页面/index.js
  • 页面/categories.js
  • 页面/类别/[slug].js

categories/[slug].js是使用Next.js提取方法名getServerSideProps即对每个请求运行,并用于在运行时构建动态页面。在categories/[slug].js该动态内容来自CMS从API端点的响应显示在网页上动态内容。动态内容只不过是一个包含 HTML<script />元素的字符串。

内容管理系统响应

注意:要从 CMS 获取内容,我们必须发送一个POST请求,其中CMS包含用户名、密码和内容的页面 slug 等凭据。我正在使用axios库发送一个 post 请求,并且该方法在post.js文件中。

post.js

import axios from 'axios';

const postCMS = async (slug) => {
    const url = `${process.env.CMS_API_URL}/render-page/`;
    let pageSlug = slug;

    // If the pageSlug is not start with `/`, then create the slug with `/`
    if (!pageSlug.startsWith('/')) {
        pageSlug = `/${pageSlug}`;
    }

    const head = {
        Accept: 'application/json',
        'Content-Type': 'application/json'
    };

    const data = JSON.stringify({
        username: process.env.CMS_API_USERNAME,
        password: process.env.CMS_API_PASSWORD,
        slug: pageSlug
    });

    try {
        const response = await axios.post(url, data, {
            headers: head
        });
        return response.data;
    } catch (e) {
        return e;
    }
};

export default postCMS;
Run Code Online (Sandbox Code Playgroud)

但是对于categories/[slug].js页面上的呈现内容,我使用Reactjs道具名称危险SetInnerHTML来呈现所有 HTML,其中还包含<script />JSON 字符串中的元素。

页面/类别/[slug].js

<div dangerouslySetInnerHTML={{ __html: result.html }} /> 
Run Code Online (Sandbox Code Playgroud)

根据每个 slug,内容加载良好。但是当我导航到该类别页面时,即pages/categories/index.js.

<Link href="/categories/[slug]" as="/categories/online-cloud-storage">
      <a>Online Cloud Storage</a>
</Link>
Run Code Online (Sandbox Code Playgroud)

它有一个<Link />元素,当我点击它时。

动态内容加载正常,但动态内容包含的元素accordionslider它们不起作用的元素。我觉得<script />这些元素是行不通的。但是当我刷新页面时,它们工作正常。看到这个。

预览问题

当我像这样设置链接时,它们也能正常工作。

<Link href="/categories/online-cloud-storage" as="/categories/online-cloud-storage">
          <a>Online Cloud Storage</a>
 </Link>
Run Code Online (Sandbox Code Playgroud)

但是像上面的方法设置链接后,导致点击硬重载页面。但我不想要这个。一切都应该工作。当用户单击类别链接时。

有没有办法解决这个问题

当您从categories/index.js页面单击时,为什么内容元素不起作用

Github 仓库

代码:

页面/index.js

import React from 'react';
import Link from 'next/link';

const IndexPage = () => {
    return (
        <div>
            <Link href="/categories">
                <a>Categories</a>
            </Link>
        </div>
    );
};

export default IndexPage;
Run Code Online (Sandbox Code Playgroud)

页面/类别/index.js

import React from 'react';
import Link from 'next/link';

const Categories = () => {
    return (
        <div>
            <Link href="/categories/[slug]" as="/categories/online-cloud-storage">
                <a>Online Cloud Storage</a>
            </Link>
        </div>
    );
};

export default Categories;
Run Code Online (Sandbox Code Playgroud)

页面/类别/[slug].js

import React from 'react';
import Head from 'next/head';
import postCMS from '../../post';

const CategoryPage = ({ result }) => {
    return (
        <>
            <Head>
                {result && <link href={result.assets.stylesheets} rel="stylesheet" />}
            </Head>
            <div>
                <h1>Category page CMS Content</h1>
                <div dangerouslySetInnerHTML={{ __html: result.html }} />
            </div>
        </>
    );
};


export const getServerSideProps = async (context) => {
  const categorySlug = context.query.slug;
  const result = await postCMS(categorySlug);
  return {
    props: {
      result
    }
  };
};


export default CategoryPage;
Run Code Online (Sandbox Code Playgroud)

Nic*_*kis 0

恕我直言,我认为脚本不正确加载是由于客户端渲染(CSR)和服务器端渲染(SSR)上的脚本错误导入造成的。在这里阅读更多内容,同时也看看这篇有趣的文章。这也可以解释链接组件的有问题的行为。

就您的情况而言,我知道这种行为是由于 CSR 期间对页面及其组件的生命周期进行错误处理造成的,因为许多脚本可能需要在页面导航中正确共享(可能在 SSR 中)。我不知道问题是什么,也没有扩展的专业知识NextJS,但我相信这些脚本应该导入到一个地方,并可能在服务器上呈现,而不是在每个页面上错误导入,错误地让 CSR 来完成工作以非NextJS优化的方式。

建议的方法是为您的应用程序使用自定义Document实现(仅限 SSR),您可以在其中定义脚本。请参阅此处了解更多详细信息。另外,我想您已经为您的应用程序设置了一个自定义应用程序文件,您将在文档中使用它,以用于所有页面通用的 CSR 和 SSR 渲染(有关更多信息,请参阅此 SO 问题)。

import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    // ...
  }

  render() {
    return (
      <Html>
        <Head>
         {/*Your head scripts here*/}
        </Head>
        <body>
          <Main />
          {/*Your body scripts here*/}
          <NextScript />
        </body>
      </Html>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

Head机组件在后台做了很多工作,以便为脚本、标记等设置内容。我建议您这样做,而不是直接将脚本添加到每个页面中。


归档时间:

查看次数:

3912 次

最近记录:

5 年,5 月 前