Sunday 27 August 2023

Warning: Text content did not match. Server: "562" Client: "563" when creating a timer in Nextjs

I want to implement a competition clock using Nextjs:

  1. competitionStartTime represents the competition start time

  2. While the user enters the page, I save Math.round(Date.now() / 1000) - competitionStartTime (how long does the competition ran)

  3. Using addOneSecond and setInterval keep adding one to competitionStartTime to run the timer every second.

  4. It also has a pause function for using to pause and resume the timer

My full demo code:

"use client";

import { useState, useEffect, useRef } from "react";

function calculateModelResult(duration) {
  // simulate the model calculation time, it costs 0.3s
  for (var i = 0; i < 1000000000; i++) {
    duration + 0;
  }
  return duration * 0.1;
}

export default function Page() {
  const competitionStartTime = 1692956171;
  const [competitionRunningTime, setCompetitionRunningTime] = useState(
    Math.round(Date.now() / 1000) - competitionStartTime
  );
  const [modelResult, setModelResult] = useState(0);
  const modelIntervalRef = useRef(0);
  const competitionTimeIntervalRef = useRef(0);
  const [pause, setPause] = useState(false);
  const addOneSecond = () => setCompetitionRunningTime((prev) => prev + 1);

  useEffect(() => {
    modelIntervalRef.current = window.setInterval(() => {
      setModelResult(calculateModelResult(competitionRunningTime));
    }, 1000);

    competitionTimeIntervalRef.current = window.setInterval(() => {
      addOneSecond();
      console.log(competitionRunningTime);
    }, 1000);

    return () => {
      window.clearInterval(modelIntervalRef.current);
      window.clearInterval(competitionTimeIntervalRef.current);
    };
  }, [competitionRunningTime]);

  const pasueFunction = () => {
    if (!pause) {
      clearInterval(competitionTimeIntervalRef.current);
    } else {
      competitionTimeIntervalRef.current = setInterval(addOneSecond, 1000);
    }
    setPause((prev) => !prev);
  };
  return (
    <>
      <h1>
        Hello, the time of the match is {competitionRunningTime}, the model result is {modelResult}.
      </h1>
      <button onClick={pasueFunction}>{pause ? "Run" : "Pause"}</button>
    </>
  );
}

However, I am two errors:

Error: Text content does not match server-rendered HTML.

Warning: Text content did not match. Server: "562" Client: "563"

See more info here: https://nextjs.org/docs/messages/react-hydration-error
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

And the modelResult appears to has delay:

Hello, the time of the match is 2904, the model result is 290.3.
Hello, the time of the match is 2938, the model result is 293.7.

It needs to be calculated using the competitionRunningTime and it costs 0.3s to finish the calculation, will it affect the time update every second?

I have watched warning text content did not match, it didn't help with my current code. May I ask how can I solve it?



from Warning: Text content did not match. Server: "562" Client: "563" when creating a timer in Nextjs

No comments:

Post a Comment