React JS 应用程序在聊天应用程序中重新加载时呈现白页:如何解决?

问题描述 投票:0回答:1

问题很简单。 我有一个“主”页面,它通过表单收集数据并将该数据发送到“聊天”页面。 一切都工作得很好,直到我重新加载聊天页面,这使得所有内容都变成空白的白色。控制台中没有错误。 此时的 url 应该包含用户名和聊天室的名称,据我所知,即使在重新加载页面并获得空白页面后,该名称仍保留在 url 中。

这似乎是一个流行的问题,但到目前为止,所有建议的解决方案都对我不起作用。这是我尝试过的:

  • 更改了package.json中的“主页”

  • 尝试了整个

    /*index.html 200

  • 尝试使用 HashRouter 而不是 BrowserRouter,尝试包含基本名称 对于路由器,尝试包括浏览器历史记录

  • 尝试将React降级到早期版本

到目前为止,这些对我来说都不起作用。这是该网站的实时链接:https://cyberpunk-chat.onrender.com/

这是 github 存储库:https://github.com/mohanamisra/chat-app-full-code

无论如何,这里有一些相关代码,以防万一:

导入路由器页面:

在App.js中

import React from 'react';
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import Join from './components/Join/Join';
import Chat from './Chat';

const App = () => {
    return (
        <Router basename = "/">
            <Routes>
                <Route path='/' element={<Join/>}/>
                <Route path='/chat' element={<Chat/>}/>
            </Routes>
        </Router>
    );
};

export default App;

在Chat.js

import React from 'react';
import {useState, useEffect} from 'react';
import queryString from 'query-string';
import { useNavigate } from 'react-router-dom';
import io from 'socket.io-client';
import InfoBar from "./components/InfoBar/InfoBar";
import Input from "./components/Input/Input";
import Messages from "./components/Messages/Messages";
import TextContainer from "./components/TextContainer/TextContainer";

import './Chat.css';
const ENDPOINT = 'https://cyberpunkchat.onrender.com';

let socket;

const Chat = () => {
    const navigate = useNavigate();
    const [name, setName] = useState('');
    const [room, setRoom] = useState('');
    const [messages, setMessages] = useState([]);
    const [message, setMessage] = useState('');
    const [users, setUsers] = useState('');

    useEffect(() => {
        const {name, room} = queryString.parse(window.location.search);
        socket = io(ENDPOINT, {transports:['websocket']});
        if(!name || !room) {
            console.log('I forgot...');
        }
        else {
            setName(name);
            setRoom(room);
            socket.emit('join', {name, room}, () => {
            });
        }
    }, [ENDPOINT, navigate]);

    useEffect(() => {
        socket.on('message', (message) => {
            setMessages([...messages, message]);
        })
        socket.on("roomData", ({ users }) => {
            setUsers(users);
        });
    }, [messages]);

    const sendMessage = (event) => {
        event.preventDefault();
        if(message)
            socket.emit('sendMessage', message, () => setMessage(''));
    }

    return(
        <div className = 'outerContainer'>
            <TextContainer users = {users}/>
            <div className = 'container'>
                <InfoBar room = {room}/>
                <Messages messages = {messages} name = {name}/>
                <Input message = {message} setMessage={setMessage} sendMessage={sendMessage}/>
            </div>
        </div>
    )
}

export default Chat;

如果有任何帮助,我将不胜感激。

提前致谢!

javascript reactjs node.js express socket.io
1个回答
0
投票

您的代码中有几个错误:

  1. socket
    未在您的第二个 useEffect 挂钩中定义。
  2. 第一个钩子中可能会出现一些名称冲突,因为您的变量
    name
    room
    与函数作用域中定义的变量一致。
  3. users.js
    中,您需要在修剪之前检查
    name
    room
    是否已定义。如果客户端未定义
    name
    room
    ,这会导致服务器崩溃。

最终代码

我的格式化程序对代码进行了一些额外的更改。

chat.js(客户端)

import React from "react";
import { useState, useEffect } from "react";
import queryString from "query-string";
import { useNavigate } from "react-router-dom";
import io from "socket.io-client";
import InfoBar from "./components/InfoBar/InfoBar";
import Input from "./components/Input/Input";
import Messages from "./components/Messages/Messages";
import TextContainer from "./components/TextContainer/TextContainer";

import "./Chat.css";
const ENDPOINT = 'https://cyberpunkchat.onrender.com';
const socket = io(ENDPOINT, {
  transports: ["websocket"],
}); // ! now defined globally 

const Chat = () => {
  const navigate = useNavigate();
  const [name, setName] = useState("");
  const [room, setRoom] = useState("");
  const [messages, setMessages] = useState([]);
  const [message, setMessage] = useState("");
  const [users, setUsers] = useState("");

  useEffect(() => {
    const info = queryString.parse(window.location.search);
    const query_name = info.name; // ! to prevent name conflicts
    const query_room = info.room; // ! to prevent name conflicts
    console.log(query_name, query_room);
    if (!query_name || !query_room) {
      console.log("I forgot...");
    } else {
      setName(query_name);
      setRoom(query_room);
      socket.emit("join", { name: query_name, room: query_room }, () => {});
    }
  }, [navigate]);

  useEffect(() => {
    socket.on("message", (message) => {
      setMessages([...messages, message]);
    });
    socket.on("roomData", ({ users }) => {
      setUsers(users);
    });
  }, [messages]);

  const sendMessage = (event) => {
    event.preventDefault();
    if (message) socket.emit("sendMessage", message, () => setMessage(""));
  };

  return (
    <div className="outerContainer">
      <TextContainer users={users} />
      <div className="container">
        <InfoBar room={room} />
        <Messages messages={messages} name={name} />
        <Input
          message={message}
          setMessage={setMessage}
          sendMessage={sendMessage}
        />
      </div>
    </div>
  );
};

export default Chat;

users.js(服务器)

const users = [];

const addUser = ({ id, name, room }) => {
  if (!name || !room) return; // ! important
  name = name.trim().toLowerCase();
  room = room.trim().toLowerCase();

  const existingUser = users.find(
    (user) => user.room === room && user.name === name
  );
  if (existingUser) {
    return {
      error: "Username is taken in this room.",
    };
  }
...
© www.soinside.com 2019 - 2024. All rights reserved.