Home > OS >  Firefox: React app not populating root element with weird error
Firefox: React app not populating root element with weird error

Time:09-30

I have a react application built for production and being served by a node/express server.

I have started the server locally and also deployed it to heroku and render.com

On all these systems, Chrome and Edge have no problems and no errors when accessing the site. But: Firefox won't populate the root element and shows a weird error. Only after refreshing, Firefox shows the site perfectly.

This is the error and the corresponding code ... it doesn't make sense

TypeError: wi.get(...) is undefined
    ts Header.jsx:36
    React 7
    C scheduler.production.min.js:13
    T scheduler.production.min.js:14
    813 scheduler.production.min.js:14
    Webpack 12
react-dom.production.min.js:189:29
    React 9
    C scheduler.production.min.js:13
    T scheduler.production.min.js:14
    (Async: EventHandlerNonNull)
    813 scheduler.production.min.js:14
    Webpack 12
const availableLanguages = [
  {
    code: "he",
    name: "עברית",
    country_code: "il",
    dir: "rtl",
  },
  {
    code: "en",
    name: "English",
    country_code: "gb",
  },
  {
    code: "de",
    name: "Deutsch",
                             ^---- The error is showing for this code position! There is no code!
    country_code: "de",
  },
];

This happens on all three environments, tested from three different systems.

Does anyone know what is happening?

EDIT: Full Header.jsx

import { useState, useRef, useEffect } from "react";
import i18next from "i18next";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import useOutsideClick from "../hooks/useOutsideClick";
import useAuth from "../hooks/useAuth";
import Anchor from "./Anchor";
import "./Header.css";
import claryNextLogo from "../images/ClaryNext2.png";
import cookies from "js-cookie";

import { config } from "../Environment";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { solid } from "@fortawesome/fontawesome-svg-core/import.macro";
import { useContext } from "react";
import { WSContext } from "../App";
import { useEffectOnce } from "../hooks/useEffectOnce";
import { distributionService } from "../services/distributionService";
import MessageBox from "./MessageBox";
import useRetryFetch from "../hooks/useRetryFetch";

const availableLanguages = [
  {
    code: "he",
    name: "עברית",
    country_code: "il",
    dir: "rtl",
  },
  {
    code: "en",
    name: "English",
    country_code: "gb",
  },
  {
    code: "de",
    name: "Deutsch",         
    country_code: "de",
  },
];

function Header() {
  const currentLanguageCode = cookies.get("i18next").split("-")[0] || "en";
  const currentLanguage = availableLanguages.find(
    (l) => l.code === currentLanguageCode
  );

  const { auth, setAuth } = useAuth();
  const navigate = useNavigate();

  const dropdownRef = useRef(null);

  const retryFetch = useRetryFetch();

  const [showLanguageDropdown, setShowLanguageDropdown] = useState(false);
  const [showMessageBox, setShowMessageBox] = useState(false);
  const [msgBoxTitle, setMsgBoxTitle] = useState("");
  const [msgBoxButtons, setMsgBoxButtons] = useState({});
  const [msgBoxInputs, setMsgBoxInputs] = useState([]);
  const [msgBoxId, setMsgBoxId] = useState("");
  const [msgBoxMoreJSX, setMsgBoxMoreJSX] = useState(null);

  const [chatRequestUser, setChatRequestUser] = useState("");
  const [chatRequestProcessId, setChatRequestProcessId] = useState("");
  const [chatRequestRoomId, setChatRequestRoomId] = useState(0);

  const { t } = useTranslation();

  const { socket } = useContext(WSContext);

  const openMessageBox = (title, id, buttons, inputs, moreJSX) => {
    setMsgBoxTitle(title);
    setMsgBoxId(id);
    setMsgBoxButtons(buttons);
    setMsgBoxInputs(inputs);
    setMsgBoxMoreJSX(moreJSX);
    setShowMessageBox(true);
  };

  const onButton = async (result) => {
    console.log("MessageBox button was clicked");
    console.dir(result);

    if (result.btnId === "yes") {
      // chat was accepted, change to ShowFullLog, join room and notify user
      socket.send(
        JSON.stringify({
          command: "acceptchat",
          payload: { email: chatRequestUser, roomId: chatRequestRoomId },
        })
      );

      // collect necessary process log information
      let response = await retryFetch(
        `${config.API_BASE}/api/processes/${chatRequestProcessId}`
      );
      let process = await response.json();

      let stateToPass = {
        processId: chatRequestProcessId,
        presName: process.prescriptionName,
        presHistoryId: process.fiPrescriptionHistory._id,
        autochat: true,
      };
      if (process.fiExpert?.email === auth.email) {
        stateToPass.userEmail = process.fiInitiator?.email;
        navigate("/fulllog", { state: stateToPass });
      } else {
        stateToPass.expertEmail = process.fiExpert?.email;
        navigate("/userlog", { state: stateToPass });
      }
    } else {
      // chat was refused, send message to requesting user
      socket.send(
        JSON.stringify({
          command: "refusechat",
          payload: {
            email: chatRequestUser,
            roomId: chatRequestRoomId,
          },
        })
      );
    }
  };

  useEffect(() => {
    document.body.dir = currentLanguage?.dir || "ltr";
  }, [currentLanguage]);

  useEffectOnce(() => {
    let messageUnsubscribe = distributionService
      .getMessage()
      .subscribe((msg) => {
        console.log("Header incoming message");

        switch (msg.command) {
          case "requestchat":
            setChatRequestUser(msg.payload.email);
            setChatRequestProcessId(msg.payload.processId);
            setChatRequestRoomId(msg.payload.roomId);
            openMessageBox(
              t("msg_chat_requested", {
                user: msg.payload.email,
                processId: msg.payload.processId,
              }),
              "requestchat",
              [
                { id: "yes", text: t("yes") },
                { id: "no", text: t("no") },
              ],
              [],
              ""
            );
            break;
        }
      });

    return () => {
      // cleanup subscription
      messageUnsubscribe.unsubscribe();
    };
  }, []);

  const login = () => {
    navigate("/login");
  };

  const logout = async () => {
    let response = await fetch(config.API_BASE   "/logout", {
      credentials: "include",
    });

    if (!response.ok) alert(t("msg_error_logout"));

    let result = await response.json();
    console.log(result);
    setAuth({});

    socket.send(
      JSON.stringify({
        command: "logout",
        payload: undefined,
      })
    );

    navigate("/");
  };

  // const register = () => {
  //   navigate("/register");
  // };

  const showPrescriptions = () => {
    //navigate("/design");
    navigate("/prescriptionlist");
  };

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

  const openMenu = () => {
    setShowLanguageDropdown(true);
  };

  const closeMenu = () => {
    setShowLanguageDropdown(false);
  };

  const selectLanguage = (code) => {
    i18next.changeLanguage(code);
    setShowLanguageDropdown(false);
  };

  useOutsideClick(dropdownRef, closeMenu);

  return (
    <>
      <div className="header-menu">
        <div className="title" onClick={goHome}>
          <img src={claryNextLogo} alt="ClaryNext logo" width="90" />
        </div>
        {!auth?.email ? (
          <>
            <div className="notonmobile">
              <div>
                <Anchor
                  onClick={showPrescriptions}
                  text={t("example_prescriptions")}
                />
              </div>
            </div>
            <div className="rightflex notonmobile">
              <div className="rightMargin">
                <span>&nbsp;</span>
              </div>
              <button onClick={login}>{t("login")}</button>
              <span className="leftMargin bigger">
                <FontAwesomeIcon
                  onClick={() => openMenu()}
                  icon={solid("globe")}
                />
              </span>
            </div>
          </>
        ) : (
          <>
            <div className="rightMargin notonmobile">
              <Anchor
                onClick={showPrescriptions}
                text={t("prescriptions_and_processes")}
              />
            </div>
            <div className="rightflex notonmobile">
              <div className="rightMargin">
                <Anchor onClick={logout} text={t("logout")} />
              </div>
              <span className="smaller">{auth.email}</span>
              <span className="leftMargin bigger">
                <FontAwesomeIcon
                  onClick={() => openMenu()}
                  icon={solid("globe")}
                />
              </span>
            </div>
          </>
        )}
      </div>
      {showMessageBox ? (
        <MessageBox
          onButton={onButton}
          buttons={msgBoxButtons}
          text={msgBoxTitle}
          inputs={msgBoxInputs}
          id={msgBoxId}
          moreJSX={msgBoxMoreJSX}
          onClose={() => setShowMessageBox(false)}
        />
      ) : (
        ""
      )}
      {showLanguageDropdown ? (
        <div className="language_dropdown" ref={dropdownRef}>
          {availableLanguages.map((lang, idx) => (
            <p key={idx} onClick={() => selectLanguage(lang.code)}>
              <span
                className={`flag-icon flag-icon-${lang.country_code}`}
              ></span>
              {lang.name}
            </p>
          ))}
        </div>
      ) : (
        ""
      )}
    </>
  );
}

export default Header;

CodePudding user response:

Originally, I had the code to access the cookie in the main function scope. After I moved it into the useEffect[] callback, it started working also in Firefox.

  • Related