React 应用程序向后端服务器发出无限请求

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

我用 React 制作了一个聊天应用程序。我在显示所有聊天的 ChatWindow 组件中发现了麻烦。这些聊天是从后端服务器调用的。该组件以某种方式向后端服务器发出无限量的请求,导致其崩溃。它还同时多次缓冲聊天。我使用了开发工具中的网络选项卡,它在不到 10 秒的时间内显示了 117 个请求。我在 Sidebar.jsx 中遇到了同样的问题。看图:Output of network tab in devtools

这是 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
javascript reactjs
1个回答
0
投票

因为您使用

menuItems
作为
useEffect
中的依赖项,您在内部调用
fetchFriends
函数,该函数使用
setMenuItems
更新菜单项,从而创建无限循环,与
fetchChats

相同

你需要有一个空的依赖数组

    useEffect(() => {
        fetchFriends()
    }, [])
    useEffect(() => {
        fetchChats()
    }, [])
© www.soinside.com 2019 - 2024. All rights reserved.