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

2024-04-09

我被这个问题困扰了很多天。我在用Next.js https://nextjs.org/并有 3 页。

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

The categories/[slug].js正在使用Next.js https://nextjs.org/获取方法名称获取服务器端属性 https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering它在每个请求上运行并用于在运行时构建动态页面。这categories/[slug].js正在页面上呈现动态内容,动态内容来自 CMS 作为 API 端点的响应。动态内容只不过是一个包含 HTML 的字符串<script />元素。

Note:要从 CMS 获取内容,我们必须发送POST请求与CMS凭据,例如用户名、密码和内容的页面片段。我在用axios https://github.com/axios/axios发送 post 请求的库,方法在里面post.js file.

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;

但对于渲染内容categories/[slug].js页面,我正在使用Reactjs https://reactjs.org/道具名称危险地设置InnerHTML https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml渲染所有包含以下内容的 HTML<script />JSON 字符串中的元素。

页面/类别/[slug].js:

<div dangerouslySetInnerHTML={{ __html: result.html }} /> 

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

<Link href="/categories/[slug]" as="/categories/online-cloud-storage">
      <a>Online Cloud Storage</a>
</Link>

它有一个<Link />元素以及当我单击它时。

动态内容加载正常,但动态内容包含accordion and slider他们不起作用的元素。我认为<script />这些元素不起作用。但是当我刷新页面时它们工作正常。看到这个。

当我将链接设置为这样时,它们也可以正常工作。

<Link href="/categories/online-cloud-storage" as="/categories/online-cloud-storage">
          <a>Online Cloud Storage</a>
 </Link>

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

有没有办法来解决这个问题?

为什么当您单击categories/index.js page?

Github 仓库 https://github.com/john45321/next.js-dynamic-content

Code:

页面/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;

页面/类别/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;

页面/类别/[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;

这里的问题是<script>标签是动态地插入与dangerouslySetInnerHTML or innerHTML,不执行为HTML 5 规范 https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml0 states:

使用innerHTML 插入的脚本元素在插入时不会执行。

如果你想插入新的<script>页面最初呈现后的标签,您需要通过 JavaScript 来完成document.createElement('script')接口并附加到 DOMelement.appendChild()以确保他们被处决。

脚本的原因不工作改变路线后,但他们do work刷新页面后,该页面与 Next.js 应用程序生命周期过程相关联。

  • 如果刷新页面,Next.js 会在服务器上预渲染整个网站,并将其作为一个整体发送回客户端。因此,该网站被解析为常规静态页面,并且<script> tags are像平常一样执行。
  • 如果您更改路由,Next.js 不会刷新整个网站/应用程序,而只会刷新其中已更改的部分。换句话说,只有page组件被获取并且它是动态地插入到现有布局中替换以前的布局page。因此,<script>标签是not被执行。

简单的解决方案

让一些现有的库通过解析 HTML 字符串并重新创建 DOM 树结构来为您处理繁重的工作。下面是它在 jQuery 中的样子:

import { useEffect, useRef } from 'react';
import $ from 'jquery';

const CategoryPage = ({ result }) => {
  const element = useRef();
  useEffect(() => {
    $(element.current).html($(result.html));
  }, []);

  return (
    <>
      <Head>
        {result && <link href={result.assets.stylesheets} rel="stylesheet" />}
      </Head>
      <div>
        <h1>Category page CMS Content</h1>
        <div ref={element}></div>
      </div>
    </>
  );
};

export const getServerSideProps = async (context) => {
  /* ... */
  return { props: { result } };
}

更难的解决方案

你必须找到一种方法来提取所有<script>从 HTML 字符串中提取标签并将它们单独添加到您的页面中。最简洁的方法是修改 API 响应,以在两个单独的字符串中提供静态 HTML 和动态脚本。然后,您可以使用以下命令插入 HTMLdangerouslySetInnerHTML并在JS中添加脚本:

const scripts = extractScriptTags(result.html);    // The hard part
scripts.forEach((script) => {
  const scriptTag = document.createElement('script');
  scriptTag.innerText = script;
  element.current.appendChild(scriptTag);
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nextjs 动态路由渲染内容不起作用 的相关文章

随机推荐

  • 地图在移动设备上显示错误(使用 JQuery mobile)

    我正在使用 jQuery mobile 并且必须显示一些地图 我使用的功能是每次单击特定链接时都会创建地图 但在生成第一个地图后 其他地图显示错误 这里有一个例子 第一张地图 其他地图 我使用这样的函数 function buildMap
  • 使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

    因此 我正在寻求构建一个 lua 脚本 该脚本使用 SCAN 根据模式查找键并删除它们 原子地 我首先准备了以下脚本 local keys local done false local cursor 0 repeat local resul
  • gridview中如何合并两个单元格

    我在 gridview 中有一些数据 格式如下 A B 1 2 adeel 3 4 sml 现在我想将该行与 B 列下的空单元格合并 我该怎么做 您可以使用 layout columnSpan 或 layout rowSpan 根据需要使对
  • ExpandableListView、OnChildClickListener

    我有组列表 每个组内都有填充的子项目 我已经实现了searchview with filtered ressults and myExpandableListView 可以展开和折叠 问题是 我不知道如何处理 OnChildClickLis
  • 为什么数字类型不共享通用接口?

    我最近遇到了一个问题 我想要一个可以同时处理双精度和整数的函数 并且想知道为什么所有数字类型 包含算术运算符和比较 没有通用接口 它会让编写像这样的函数Math Min 存在无数的重载 方式更方便 引入额外的接口会是一个重大改变吗 Edit
  • 如何使用POI api读取java中的doc和docx文件

    我正在尝试读取 doc 和 docx 文件 这是代码 static String distination E static String docFileName Requirements docx public static void ma
  • 使用固定导航栏和锚标记跳转到部分的引导程序[重复]

    这个问题已经存在了 我正在尝试使用锚标记通过引导程序和固定在顶部的导航栏导航到网页的特定部分 问题是 当我单击锚链接时 它们无法正确滚动到该部分的开头 而是滚动到该部分的开头 因为页边距应用于正文 body margin top 60px
  • X.iOS Cycle7 似乎破坏了 SSL

    昨天我在 Beta 通道中将 XS 更新为 RC 版本 即 Cycle7 现在我在使用 iOS 连接到 HTTPS 连接时遇到问题 错误 Error SecureChannelFailure The authentication or de
  • 如何使用musicbrainz获取专辑图像

    我不知道我是否可以在这里问这样的问题 我的问题如下 我正在自己制作音乐播放器 我想下载那些没有专辑图像的歌曲的专辑图像 就像什么是在做 我自己做了一些搜索 我发现使用 MusicBrainz 我们可以下载图像 我查了一下它的API 但我不太
  • 使用 php 删除 xml 中标签值之间的空格

    我一直在搜索信息 当我将 PHP 代码导出到 XML 时 如何删除 PHP 代码留下的标记值之间的空格 我将详细解释 首先加载 XML 然后使用 xPath 对文件进行搜索 然后删除一些元素与某些品牌不匹配 最后我将其重新导出为新的 XML
  • numpy正半定警告

    在我正在编写的Python脚本中 我正在使用表达式模拟多元正态随机向量 np random multivariate normal np zeros dim obs y cov 我的脚本运行 但生成以下警告 RuntimeWarning c
  • html5/jquery后退按钮

    是否有一个库或一段代码可以使特定按钮充当正确的浏览器后退按钮 它将带您到之前加载的上一个页面 目前我只是指定href我假设的是之前加载的页面 但得出的结论是这不起作用 因为可以从不同的屏幕访问一个屏幕 是否有这样的示例 或者我是否需要创建自
  • Android:从另一个片段打开一个片段

    我是 Android 新手 这是我的第二个应用程序 我正在创建一个选项卡式活动 其中第一个片段具有用于创建新任务的表单 第二个片段具有所有已保存任务的列表 第三个片段将在从第二个片段的列表中选择时显示对任务的评论分段 第三个片段也应该像一个
  • 如何将 WSGI 中的首选编码设置为 UTF-8

    感觉这里有点疯狂 我已经使用 mod wsgi 设置了 Apache 但我无法使编码正常工作 我有 测试 mod wsgi 是否在守护进程模式下运行 read 格雷厄姆 邓普尔顿的博客文章 http blog dscpl com au 20
  • ReportLab 表的列跨越 PDF 页面上的所有行?

    我正在尝试按以下格式在 reportLab 中布局表格 该表是动态的并且可以有很多行 a b a a tTableStyle SPAN 1 0 1 1 如果表格适合一页 则工作正常 但如果表格分为几页 则崩溃 如果没有跨度 表格可以正常分割
  • 带有时态表的 Entity Framework Core 3.1 - 访问 SysStartTime 和 SysEndTime

    我已经基于 Microsoft SQL 文档创建了时态表使用默认历史表创建临时表 https learn microsoft com en us sql relational databases tables creating a syst
  • 将 Pylons 控制器作为单独的应用程序运行?

    我有一个 Pylons 应用程序 我想将一些逻辑移动到单独的批处理过程中 我一直在主应用程序下运行它进行测试 但它将在数据库中执行大量工作 我希望它是一个单独的进程 将在后台不断运行 主 pylons 应用程序会将作业提交到数据库中 新进程
  • 如何在 android 中构建支持旧 SDK 版本 (minSdkVersion) 的应用程序

    当通过向导创建新项目并给出错误时 那就太沮丧了 我只是使用 MinSdk 9 创建新项目以使应用程序在姜饼上运行 这给了我以下错误 Error Execution failed for task app processDebugManife
  • 如何让 Discord 机器人异步等待多条消息的反应?

    tl dr 我的机器人如何异步等待多条消息的反应 我正在向我的 Discord 机器人添加石头剪刀布 rps 命令 用户可以通过输入调用命令 rps以及一个可选参数 指定要玩的用户 rps TrebledJ 被调用时 机器人将直接向调用它的
  • nextjs 动态路由渲染内容不起作用

    我被这个问题困扰了很多天 我在用Next js https nextjs org 并有 3 页 页面 index js 页面 categories js 页面 类别 slug js The categories slug js正在使用Nex