What’s the correct way to render a component on data change in the database? React

I working on a MERN project for learning purposes (not YT follow-up). I have a user model with a rank of 0 as default and with different score fields. I have created an endpoint that when the score fields meet certain conditions, the user rank gets updated 1. So far so good here and it works. My next step is to show a ‘you ranked up’ pop-up when the user rank changes and I am not sure what the best practice is for that. It’s a math-practice challenge and I want the pop-up to show between the end of the game and final score component. Any help is appreciated.

Endpoint:

import User from "../models/userModel.js";
import jwt from "jsonwebtoken";
import asyncHandler from "express-async-handler";

export const rankUp = asyncHandler(async (req, res) => {
  // Extract token from headers
  const token = req.headers.authorization.split(" ")[1];

  // Find the user by token
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  // Find user by id
  const user = await User.findOne({ _id: decoded.id });

  if (!user) {
    return res.status(404).send("User not found");
  }

  let newRank;

  if (
    user.userStats.totalScore === 5000 &&
    user.userStats.totalAdditionScore >= 1000 &&
    user.userStats.totalAdditionScore >= 1000 &&
    user.userStats.totalSubtractionScore >= 1000 &&
    user.userStats.totalMultiplicationScore >= 1000 &&
    user.userStats.totalOrderedScore >= 1000
  ) {
    newRank = 1;
  } else {
    throw new Error('Conditions not met')
  }

  // Save the updated user
  const updatedUserRank = await User.findByIdAndUpdate(
    { _id: decoded.id },
    { $set: { userRank: newRank } },
    { new: true }
  );

  if (updatedUserRank) {
    res.json({updatedUserRank});
  } else {
    res.status(400);
    throw new Error("Something went wrong");
  }
});

The component that I want to show the pop-up:

import { Divider, List, TextField, Typography } from "@mui/material";
import React, { useEffect } from "react";
import Navbar from "../components/Navbar";
import Container from "@mui/material/Container";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import { useState } from "react";
import { useNavigate } from "react-router";
import GameInfo from "./GameInfo";
import { useSelector, useDispatch } from "react-redux";

import {
  earnLife,
  gainPoints,
  gainTime,
  isFinished,
  loseLife,
  loseTime,
  restart,
} from "../features/gameSlice";
import { updateScore } from "../statsHandler";

const correctAnswer = <Typography>Correct!</Typography>;
const wrongAnswer = <Typography>Wrong!</Typography>;
const enterAnswer = <Typography>Enter your answer!</Typography>;

const MainInput = ({ operation, calculation }) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [correctValue, setCorrectValue] = useState(false);
  const [calculatedNums, setCalculatedNums] = useState({});
  const [isIncorrect, setIsIncorrect] = useState(false);
  const [generateNewNumbers, setGenerateNewNumbers] = useState(false);
  const [haveToEnterAnswer, setHaveToEnterAnswer] = useState(false);
  const [streak, setStreak] = useState(0);

  const seconds = useSelector((state) => state.game.seconds);
  const points = useSelector((state) => state.game.points);
  const lives = useSelector((state) => state.game.lives);
  const gameOver = useSelector((state) => state.game.isFinished);
  const gameStart = useSelector((state) => state.game.startGame);

  const user = JSON.parse(localStorage.getItem("user"));

  const token = user.token;

  let finalScore = points;

  const navigate = useNavigate();

  // FIX THE UNDEFINED ISSUE

  // FIX THE UNDEFINED ISSUE

  // FIX THE UNDEFINED ISSUE

  useEffect(() => {
    if (gameOver) {
      updateScore(finalScore, operation, token);
    }
  }, [gameOver]);

  useEffect(() => {
    if (correctValue && streak === 4 && lives < 4) {
      dispatch(earnLife());
      setStreak(0);
    }
  }, [streak]);

  useEffect(() => {
    setCalculatedNums(calculation());
    setGenerateNewNumbers(false);
    setCorrectValue(false);
    setEnteredValue("");
  }, [generateNewNumbers]);

  const dispatch = useDispatch();

  const timerValid = lives > 0 && seconds > 0 && gameStart;

  const newChallenge = () => {
    setIsIncorrect(false);
    setHaveToEnterAnswer(false);
    dispatch(restart());
  };

  const handleCount = () => {
    if (timerValid) {
      dispatch(loseTime());
    }
  };

  useEffect(() => {
    if (lives === 0 || seconds === 0) {
      dispatch(isFinished());
    }
  }, [lives, seconds]);

  useEffect(() => {
    let interval;
    if (timerValid) {
      interval = setInterval(() => {
        handleCount();
        if (lives === 0 || seconds === 0) {
          clearInterval(interval);
        }
      }, 1000);
    }
    return () => {
      clearInterval(interval);
    };
  }, [timerValid]);

  const submitHandler = () => {
    if (correctValue) {
      setGenerateNewNumbers(true);
      dispatch(gainPoints());
      dispatch(gainTime());
      setStreak(streak + 1);
      console.log(user);
    }

    if (+enteredValue === calculatedNums.result) {
      setCorrectValue(true);
    } else if (enteredValue.length === 0) {
      setHaveToEnterAnswer(true);
    } else {
      setIsIncorrect(true);
      dispatch(loseLife());
      setStreak(0);
    }
  };

  const inputValueHandler = (value) => {
    setIsIncorrect(false);
    setHaveToEnterAnswer(false);
    setEnteredValue(value);
  };

  const submitOrTryNewOne = () => {
    return correctValue ? "Try new one" : "Submit";
  };

  const goHome = () => {
    navigate("/");
    dispatch(restart());
  };

  return (
    <>
      <Navbar />

      {seconds && lives > 0 ? (
        <>
          <GameInfo />
          <Container component="main" maxWidth="xs">
            <Box
              sx={{
                marginTop: 8,
                display: "flex",
                flexDirection: "column",
                alignItems: "center",
              }}
            >
              <Typography>
                Fill in the box to make the equation true.
              </Typography>

              <Typography fontSize={28}>
                {operation !== "/"
                  ? `${calculatedNums.number1} ${operation} ${calculatedNums.number2}`
                  : `${calculatedNums.number2} ${operation} ${calculatedNums.number1}`}{" "}
                =
              </Typography>

              <TextField
                inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }}
                type="number"
                name="sum"
                id="outlined-basic"
                label=""
                variant="outlined"
                onChange={(event) => {
                  inputValueHandler(event.target.value);
                }}
                disabled={correctValue}
                value={enteredValue}
              ></TextField>
              {haveToEnterAnswer && enterAnswer}
              {correctValue && correctAnswer}
              {isIncorrect && wrongAnswer}

              <Button
                type="button"
                sx={{ marginTop: 1 }}
                onClick={() => submitHandler()}
                variant="outlined"
              >
                {isIncorrect ? "Try again!" : submitOrTryNewOne()}
              </Button>
            </Box>
          </Container>
        </>
      ) : (
        <>
          <List
            sx={{
              marginTop: 8,
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
            }}
          >
            <Typography fontSize={28}>GAME OVER</Typography>
            <Divider></Divider>
            <Typography sx={{ marginTop: 2 }} fontSize={28}>
              Final Score: {points}
            </Typography>
            <Divider></Divider>
            <Button
              sx={{ marginTop: 2 }}
              variant="contained"
              size="large"
              onClick={newChallenge}
            >
              New Challenge
            </Button>
            <Button
              sx={{ marginTop: 2 }}
              variant="contained"
              size="large"
              onClick={goHome}
            >
              Home Page
            </Button>
          </List>
        </>
      )}
    </>
  );
};

export default MainInput;