NextJS 水合错误(文本内容与服务器渲染的 HTML 不匹配。)

2023-12-26

仅在部署应用程序时出现两个错误,而不是在开发模式或本地构建中,这完全是另一个问题。

第一个错误:文本内容与服务器呈现的 HTML 不匹配。

第二个错误:补水时出现错误。由于错误发生在 Suspense 边界之外,因此整个根将切换到客户端渲染。

我发现这些错误是由我从 Unix 时间戳格式 (current.dt) 的 API 获取的时间格式引起的,但我不知道如何处理此问题。我应该在服务器上(即 getServerSideProps 中)格式化日期吗?或者这些错误是由其他原因引起的?

Edit:实时应用程序有错误:https://weather-test-mu.vercel.app/ https://weather-test-mu.vercel.app/

天气显示:

import type { Current, Location } from '../../types/typeWeatherApi';

const WeatherDisplay = ({
    location,
    current,
}: {
    location: Location;
    current: Current;
}) => {
    // This causes the errors:
    const hour = ('0' + new Date(current.dt * 1000).getHours()).slice(-2);
    const minutes = ('0' + new Date(current.dt * 1000).getMinutes()).slice(-2);
    const currentTime = `${hour}:${minutes}`;

    return (
        <article>
            <h1>{location.name}</h1>
            <p>{location.country}</p>
            <p>{current.feels_like}</p>
            {/* This causes the error: */}
            <p>{currentTime}</p>
        </article>
    );
};

export default WeatherDisplay;

带有 getServerSideProps 的索引页:

import axios from 'axios';
import { useState } from 'react';

import type { NextPage, GetServerSideProps } from 'next';
import type { Data, Location } from '../types/typeWeatherApi';

import { getCurrentWeather } from './api/currentWeather';
import { getCurrentLocation } from './api/currentLocation';

import WeatherDisplay from '../components/weather-display/weather-display';

const Home: NextPage = ({ initialWeather, initialLocation }: any) => {
    const [location, setLocation] = useState<Location>(initialLocation);
    const [weatherData, setWeatherData] = useState<Data>(initialWeather);
    const [units, setUnits] = useState('metric');
    const [lang, setLang] = useState('en');

    const getGeolocationData = () => {
        navigator.geolocation.getCurrentPosition(
            (position) => {
                axios
                    .get(
                        `/api/currentLocation?lon=${position.coords.longitude}&lat=${position.coords.latitude}`
                    )
                    .then((response) => setLocation(response.data[0]));
            },
            (error) => {
                console.warn(`ERROR(${error.code}): ${error.message}`);
            },
            {
                timeout: 10000,
                maximumAge: 0,
            }
        );
    };

    const getCurrentWeather = async () => {
        await axios
            .get(
                `/api/currentWeather?lon=${location.lon}&lat=${location.lat}&units=${units}&lang=${lang}`
            )
            .then((response) => setWeatherData(response.data))
            .catch((error) => console.error(error));
    };

    return (
        <>
            <section>
                <div>
                    <p>Latitude: {location.lat}</p>
                    <p>Longitude: {location.lon}</p>
                </div>
                <button onClick={getGeolocationData}>Get Current Location</button>

                <button onClick={getCurrentWeather}>Get Current Weather</button>
            </section>
            <section className="current-weather">
                <WeatherDisplay location={location} current={weatherData.current} />
            </section>
        </>
    );
};

export const getServerSideProps: GetServerSideProps = async () => {
    const defaultWeatherQuery = {
        lat: '51.5072',
        lon: '0.1276',
        exclude: '',
        units: 'metric',
        lang: 'en',
    };

    const defaultLocationQuery = {
        lat: defaultWeatherQuery.lat,
        lon: defaultWeatherQuery.lon,
    };

    const defaultWeather = await getCurrentWeather(defaultWeatherQuery);
    const defaultLocation = await getCurrentLocation(defaultLocationQuery);

    return {
        props: {
            initialWeather: defaultWeather,
            initialLocation: defaultLocation[0],
        },
    };
};

export default Home;


我得到了答复GitHub 讨论 https://github.com/vercel/next.js/discussions/38263在 next.js 上,我会将其粘贴到此处,以便任何与我面临相同问题的人:

Quote 冰冷的约瑟夫 https://github.com/icyJoseph:

Hi,

是的,这两个错误结合在一起了。

因为客户端在第一帧上需要看到与 服务器发送过来,以便放置事件监听器并放置 兄弟姐妹和孩子正确,如果在这期间有错误 完成后,React 会记录一个错误。这件事一直发生在 反应 17 据我所知。

第二个问题由新的渲染根开始,它看到了这个 作为渲染错误,这对并发特性不友好,所以 水合作用失败,一切都被抛到了九霄云外。

至少我是这样解释第二个错误的。很多人只是 忽略了第 1 号错误,在 React 17 发布的整整 2 年里, 并不是说你这样做了,但许多人使用了这样做的库,而其他人只是 忽略了他们。可能的解决方法

时间和随机性是最常见的两个因素 这。

我会这样解决这个问题:

  1. 让服务器呈现时间,但采用 UTC 格式
  2. (可选)放置 CSS 使其隐藏,但仍显示在布局上(不显示任何内容)
  3. 从客户端,更新到正确的时区,也使时间可见
import { CSSProperties, useEffect, useState } from "react";
import { Example } from "../components/Example";

const TimeDisplay = ({ time }: { time: number }) => {
  const [currentTime, setCurrentTime] = useState(() => {
    const hour = ("0" + new Date(time * 1000).getUTCHours()).slice(-2);
    const minutes = ("0" + new Date(time * 1000).getUTCMinutes()).slice(-2);

    return `${hour}:${minutes} UTC`;
  });

  useEffect(() => {
    setCurrentTime(() => {
      const hour = ("0" + new Date(time * 1000).getHours()).slice(-2);
      const minutes = ("0" + new Date(time * 1000).getMinutes()).slice(-2);

      return `${hour}:${minutes}`;
    });
  }, [time]);

  // optionally make this content take space, but remain invisible, to avoid layout shifts
  // it's better to use a CSS class instead
  const style: CSSProperties = {
    visibility: currentTime.includes("UTC") ? "hidden" : "visible",
  };

  return (
    <article>
      <p style={style}>{currentTime}</p>
    </article>
  );
};

我建议还混合使用 DateTimeFormat API,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat, 它可以为您显示时区:

const date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0, 200));

options = {
  hour: 'numeric', minute: 'numeric', second: 'numeric', 
  timeZoneName: 'short' 
};

console.log(new Intl.DateTimeFormat('sv-SE', options).format(date));

如果我在repl https://replit.com/languages/javascript,我得到 3:00:00 AM UTC (这将是 你的服务器发送的内容),但如果我在我得到的浏览器上运行它, 欧洲中部时间 4:00:00。

您页面的源代码包含服务器看到的时间。

由于用户从不同的时区到达您,您必须 考虑显示 UTC 的框架,然后显示时间 用户时区。将此与 CSS 可见性结合起来效果很好, 因为你可以避免布局变化等,所以时间会花掉 的地方,但它不会被看见。

机器人、爬虫依然能看到时间,对于禁用 JS 的用户来说, 您可以添加一个标签,使日期再次可见。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NextJS 水合错误(文本内容与服务器渲染的 HTML 不匹配。) 的相关文章

随机推荐

  • 单击小部件时播放声音

    这是我的代码 它打开主要活动 但我似乎找不到一种方法来让小部件播放声音 我尝试过了 向小部件添加一个按钮 不起作用 add an OnClickListener到主要活动 有效 但它打开主要活动 我只想要声音而不是活动 编写一个新方法来播放
  • 了解 ASP.NET WebForms 中控件处于生命周期的哪个阶段

    从控件的外部 是否可以找出特定控件或页面处于页面生命周期的哪个阶段 初始化 加载 预渲染等 例如 在伪代码中 if myControl CurrentLifeCycle Lifecycle Init do something 恐怕没有内置函
  • Qt QSqlQuery 准备和bindValue 不工作

    我在准备和绑定值时遇到问题 db open QSqlQuery q q prepare SELECT id malade nom prenom FROM Malade WHERE nom LIKE p OR prenom f q bindV
  • 如何使用 SetWindowsHookEx 和 WH_KEYBOARD 挂钩外部进程

    我试图挂钩例如记事本但没有成功 制作一个全局钩子似乎效果很好 在 XP SP2 上测试 编辑 修改后的代码现在可以使用 MyDLL代码 include
  • 如何以编程方式打印各种文件类型

    我正在编写一个应用程序 它执行一些测试并生成许多不同的报告 这些可以是标签 最终客户的 PDF 维修部门的 PDF XML 文件等的任意组合 根据报告类型 我需要将文件发送到文件系统或多种不同打印机 A4 标签等 之一 理想情况下不应该有弹
  • F# 是否具有与 C# 的“不安全”块等效的语法

    大量的数组边界检查会降低速度 对于二维数组尤其如此 有没有办法在 F 中编写不安全的代码块 我不是一个F http cs hubfs net blogs f team archive 2006 08 15 506 aspx程序员 但据我所知
  • 如何取消订阅使用 lambda 表达式的事件?

    我有以下代码让 GUI 响应集合中的更改 myObservableCollection CollectionChanged sender e gt UpdateMyUI 首先 这是一个好方法吗 第二 取消订阅此活动的代码是什么 是否相同 但
  • 如何在不指定变量来保存其 OUT 参数的情况下调用 PL/SQL 过程?

    我想调用指定了 OUT 参数的 PL SQL 存储过程 但我不关心返回值 我只关心程序是否成功执行 即没有抛出异常 我是否必须在调用 PL SQL 块中定义一个虚拟变量才能接收 out 参数 即使我不想要它 它使我的调用代码变得混乱 是的
  • 运行 Spark 作业时 CPU 使用率低

    我正在运行 Spark 作业 我有 4 个核心 工作内存设置为 5G 应用程序主机位于同一网络中的另一台计算机上 并且不托管任何工作程序 这是我的代码 private void myClass configuration of the sp
  • super(&nil) 在 ruby​​ 中做什么?

    我正在读书并发 ruby 的源代码 https github com ruby concurrency concurrent ruby blob master lib concurrent executor abstract executo
  • 在 Python 中并行处理大型 .csv 文件

    我正在使用 Python 脚本处理大型 CSV 文件 大约有 10M 行的几个 GB 的量级 这些文件具有不同的行长度 并且无法完全加载到内存中进行分析 每一行都由我的脚本中的函数单独处理 分析一个文件大约需要 20 分钟 看来磁盘访问速度
  • ASP.NET 身份验证

    我有以下登录页面 用户在其中输入用户名和密码 有了这些信息 我需要确保它们是 Admin1 角色的一部分 如果是这样 我想在用户的计算机上设置一个 cookie 使用下面的 User InRole 代码 它不会进入 if 语句 如果我取消注
  • 为什么 Android 2.3 中包含的本机 SIP 堆栈无法在 3g 上工作?

    我想知道为什么 Android 框架 自 2 3 起 中包含的本机 SIP 堆栈不能在 3g 上工作 这是否与谷歌对其合作伙伴可能有的任何法律或限制有关 此外 有人知道是否有计划取消该限制吗 Thx In 姜饼 http androidxr
  • 有选择地禁用多对多链接表上的级联删除

    是否可以有选择地删除 Entity Framework 5 Code First 中自动生成的多对多链接表上的级联删除选项 这是一个需要它的简单示例 public class Parent public int Id get set pub
  • Bootstrap中如何自动调整行高?

    我正在学习 Bootstrap 我正在尝试找出如何在给定以下条件的情况下自动调整行高 一个内有 3 行容器流体 row1必须调整其内容的高度 row3必须调整到其内容的高度并位于视口的底部 row2应调整其高度以适应之间的空间row1 an
  • 邀请好友参加活动 Facebook api

    我的脚本在邀请用户参加活动时非常慢 因为它必须检查用户是否已被邀请参加活动 否则会出现 facebook ouath 错误 我可以让它更快吗 foreach POST friends as ids if i lt 199 iZ facebo
  • Oracle 将 RAW 转换为日期格式

    我的 Oracle 数据库中有一个 RAW 字段 表示用户在系统中注册的日期 值是这样的24E2321A0000000000但是我需要将值转换为它代表的日期 等2008 12 25 15 04 31 我尝试过totimestamp see这
  • C# 情感分析 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个 最好是开源的 C 库可以用来计算某些给定文本的整体情绪 查看基于朴素贝叶斯分类的开源情感
  • 在键级别合并字典,然后在值级别合并字典

    我有两本字典 比如 Dictionary
  • NextJS 水合错误(文本内容与服务器渲染的 HTML 不匹配。)

    仅在部署应用程序时出现两个错误 而不是在开发模式或本地构建中 这完全是另一个问题 第一个错误 文本内容与服务器呈现的 HTML 不匹配 第二个错误 补水时出现错误 由于错误发生在 Suspense 边界之外 因此整个根将切换到客户端渲染 我