只有在部署应用程序时,我才有两个错误,不是在开发模式下,也不是在本地构建,这是另一个问题.

1st error:文本内容与服务器呈现的HTML不匹配.

2nd error:补水时出错.因为错误发生在悬念边界之外,所以整个根将切换到客户端渲染.

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

Edit:出现错误的Live app:https://weather-test-mu.vercel.app/

WeatherDisplay:

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;

Index page with 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 discussions分的回复.js,我会把它贴在这里,给任何和我面临同样问题的人:

报价icyJoseph:

你好

是的,所以这两个错误是结合在一起的.

因为客户端在第一帧上需要看到与服务器发送的HTML相同的HTML,以便正确放置事件侦听器和同级和子级,如果在执行此操作时出现错误,React会记录错误.这件事一直发生在17岁的时候.

第二个问题是新的渲染根,它将此视为渲染错误,这对并发功能不友好,因此水合作用失败,并将整个内容抛出窗口.

至少我是这样解释第二个错误的.很多人只是忽略了错误1,在整整两年的时间里,17个被淘汰了,并不是说你被淘汰了,但很多人使用了那些被淘汰的库,而其他人只是忽略了它们.

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

我会这样处理这个问题:

  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,它可以为您显示时区:

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上运行上述命令,我会得到UTC凌晨3:00:00(这将是您的服务器发送的),但如果我在我得到的浏览器上运行,则会得到CET下午4:00.

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

由于用户来自不同的时区,因此您必须说明显示UTC的帧,然后显示用户时区的时间.将其与CSS可见性相结合是很好的,因为您可以避免布局的变化,这样,时间就会取而代之,但它将不可见.

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

Javascript相关问答推荐

如何使用侧边滚动按钮具体滚动每4个格?

使用续集和下拉栏显示模型属性

Chart.js V4切换图表中的每个条,同时每个条下有不同的标签.怎么做?

未捕获错误:在注销后重定向到/login页面时找不到匹配的路由

为什么promise对js中的错误有一个奇怪的优先级?

我们如何从一个行动中分派行动

Websocket错误—有一个或多个保留位开启:reserved1 = 1,reserved2 = 0,reserved3 = 0

如何从HTML对话框中检索单选项组的值?

我怎么在JS里连续加2个骰子的和呢?

当用户点击保存按钮时,如何实现任务的更改?

在css中放置所需 colored颜色 以填充图像的透明区域

Reaction组件在本应被设置隐藏时仍显示

将对象推送到数组会导致复制

按特定顺序将4个数组组合在一起,按ID分组

如何在Reaction中清除输入字段

如何在每隔2分钟刷新OKTA令牌后停止页面刷新

更改管线时不渲染组件的react

需要从对象生成列表

如何格式化API的响应

如何在单击Search按钮时更新Reaction组件?