Firefox下React生产环境应用根元素无法渲染的异常排查
Firefox首次访问React生产应用时抛出TypeError,刷新后恢复正常
我有一个构建为生产环境的React应用,由Node/Express服务器提供服务。本地启动服务器及部署到Heroku、Render.com后,Chrome和Edge访问均正常无报错,但Firefox首次访问时无法填充根元素,抛出如下异常:
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", ^---- 错误指向此处,但无代码! country_code: "de", }, ];
该问题在本地、Heroku、Render.com三个环境,三台不同设备上均能复现,刷新Firefox后页面显示正常。完整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> </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;
请问有人知道这是什么原因吗?
内容的提问来源于stack exchange,提问作者devnull69
相关产品推荐
相关产品推荐

