我用 React 制作了一个聊天应用程序。我在显示所有聊天的 ChatWindow 组件中发现了麻烦。这些聊天是从后端服务器调用的。该组件以某种方式向后端服务器发出无限量的请求,导致其崩溃。它还同时多次缓冲聊天。我使用了开发工具中的网络选项卡,它在不到 10 秒的时间内显示了 117 个请求。我在 Sidebar.jsx 中遇到了同样的问题。看图:
这是 Sidebar.jsx:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Menu, Drawer, Button } from 'react-daisyui';
const api = `http://localhost:8000`;
function Sidebar({ onRecipientChange }) {
const [menuItems, setMenuItems] = useState([])
const [nick, setNick] = useState('')
const handleFriendSelect = (nickname, email) => {
onRecipientChange(nickname, email)
}
const fetchFriends = (async () => {
if (!window.localStorage.getItem('e')) {
const response = await axios.get(`${api}/users/profile/friends?email=${window.localStorage.getItem('mail')}`);
const res = response.data.values;
const frnds = JSON.parse(res);
let items = [];
if (Array.isArray(frnds) && frnds.length > 0 && res !== '["Start"]') {
const requests = frnds.map(async (friend) => {
const r = await axios.get(`${api}/users/profile?email=${friend}`);
return r.data.values[0].nickname;
});
const nicknames = await Promise.all(requests);
items = nicknames.map((nickname, index) => (
<Menu.Item onClick={() => handleFriendSelect(nickname, frnds[index])} style={{ borderRadius: 3 }}>
{(nickname) ? nickname : "None"}
</Menu.Item>
));
} else {
items.push(
<Menu.Item key="None" style={{ borderRadius: 3 }}>
None
</Menu.Item>
);
}
setMenuItems(items);
}
})
useEffect(() => {
fetchFriends()
}, [menuItems])
useEffect(() => {
async function fetchNick() {
if (!window.localStorage.getItem('e')) {
const res = await axios.get(`${api}/users/profile?email=${window.localStorage.getItem('mail')}`)
setNick(res.data.values[0].nickname)
}
}
fetchNick()
}, []);
return (
<>
<div>
<Drawer open={true} side={
<>
<Menu className="bg-base-200 rounded-sm text-lg h-full" style={{ width: 250 }}>
<Menu.Title className='text-xl' style={{ color: 'gray' }}>
<span className='flex justify-between'>
{nick}
<Button
color='ghost' size='sm' className='btn-circle'
onClick={
async function logout() {
window.localStorage.removeItem('mail')
window.location = '/login'
}
}
>
</Button>
</span>
</Menu.Title>
<Menu.Item>
<Menu.Title className='text-lg'>Me</Menu.Title>
<Menu.Item style={{ borderRadius: 3 }}>
Profile
</Menu.Item>
<Menu.Item style={{ borderRadius: 3 }}>
Inbox
</Menu.Item>
<Menu.Item style={{ borderRadius: 3 }}>
Friends
</Menu.Item>
</Menu.Item>
<Menu.Item>
<Menu.Title className='text-lg'>Chats</Menu.Title>
{menuItems}
</Menu.Item>
</Menu>
</>
} />
</div>
</>
);
}
export default Sidebar
这是 ChatWindow.jsx:
import { useEffect, useState } from 'react';
import { Button, Navbar, Input, Join, ChatBubble } from 'react-daisyui';
import axios from 'axios'
const api = `http://localhost:8000`;
function ChatWindow({ recipientNickname, recipientEmail }) {
const client = window.localStorage.getItem('mail')
const [chats, setChats] = useState([])
async function fetchChats() {
try {
const response = await axios.get(`${api}/users/messages?client=${client}&recipient=${recipientEmail}`);
if (response.data) {
setChats(response.data);
} else {
setChats([]);
}
} catch (e) {
console.log(e);
}
}
useEffect(() => {
fetchChats()
}, [chats])
const chatBubbles = chats.map((message, index) => (
<ChatBubble key={index} end={message.client === client}>
<ChatBubble.Message>{message.message}</ChatBubble.Message>
</ChatBubble>
))
return (
<div style={{ margin: 250, marginTop: 0, zIndex: 1 }}>
<div>
<Navbar>
<Navbar.Center style={{ alignItems: 'center' }}>
<Button tag="a" color="ghost" className="normal-case text-xl">
{recipientNickname || "Chats"}
</Button>
</Navbar.Center>
</Navbar>
</div>
<div className='chats'>
{chatBubbles}
</div>
<div>
<div style={{ position: 'fixed', bottom: 5, left: 0, right: 0 }}>
<Join>
<Input style={{ width: 1000, marginLeft: 260 }} placeholder='Send a message' className='join-item' />
<Button className='join-item rounded-s' color='success'>
Send
</Button>
</Join>
</div>
</div>
</div>
)
}
export default ChatWindow
因为您使用
menuItems
作为 useEffect
中的依赖项,您在内部调用 fetchFriends
函数,该函数使用 setMenuItems
更新菜单项,从而创建无限循环,与 fetchChats
相同
你需要有一个空的依赖数组
useEffect(() => {
fetchFriends()
}, [])
useEffect(() => {
fetchChats()
}, [])