发送消息时渲染发送和接收的消息

时间:2021-02-03 02:52:00

标签: javascript reactjs django typescript react-router-dom

我正在尝试仅使用 React js 和 Django 构建聊天应用程序。当我在输入中键入消息并点击发送时,它会获取输入并将其发送到 API,API 返回消息并使用 useEffect 呈现它,接下来如果我收到回复,我也想呈现它,问题是:-

1) 当我点击发送时,我收到内部服务器错误状态 500,但我将消息发送到的号码正在接收消息,这意味着正在发送消息。 2)当useEffect在发送消息后运行时,它不断地开始运行并且不会停止。 3) 我只收到传递的消息,而不是从 api 收到的消息。

请帮我解决这些问题。 聊天组件:

import React, { useEffect, useState } from 'react'
import ArchiveOutlinedIcon from '@material-ui/icons/ArchiveOutlined';
import './chat.css'
import { IconButton } from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
//ICONS
import SendIcon from '@material-ui/icons/Send';
import NoteIcon from '@material-ui/icons/Note';
import { Link, useParams } from 'react-router-dom';
import axios from 'axios';


interface ParamTypes {
    userId: string
}

const ChatBox = () => {
    const { userId } = useParams<ParamTypes>()
    const [messages, setMessages] = useState<any[]>([])
    const [formInput, setFormInput] = useState<any>({
        to: '',
        body: ''
    })

    //FETCHING SMS LIST WHEN RENDERED 2)RE-RENDER WHENuserId changes
    useEffect(() => {
        //GET SMS LIST FROM BACKEND
        const getData = async () => {
            console.log('Room Id', userId);
            return await axios.get(`http://206.189.138.105/api/sms/v1/list-sms/${userId}/`)
                .then((response) => {
                    setMessages(response.data)
                    console.log('list sms', response.data)
                    // console.log('list response', response)

                }).catch((err) => console.log(err)
                )

        }
        getData()
        return () => {
            getData()
        }

    }, [userId])



    //HANDLE FORM INPUT CHANGES
    const handleChange = (name: any) => (event: any) => {
        setFormInput({
            ...formInput,
            to: userId,
            [name]: event.target.value
        })
    }

    const getFormData = (object: any) => {
        const formData = new FormData();
        Object.keys(object).forEach(key => formData.append(key, object[key]));
        return formData;
    }
    //SENDMESSAGE
    const sendMessages = async (event: any) => {
        event.preventDefault()
        console.log('send-clicked', formInput);

        await axios.post('http://206.189.138.105/api/sms/v1/send-sms', getFormData(formInput))
            .then((response) => {
                setMessages(response.data)
                setFormInput({})
                console.log('addnewmsgInputs', response.data)
            }).catch((err) => console.log(err)
            )


    }


    return (
        <div className="chat">
            {/* //HEADER */}
            <div className="chat__header">
                <div className="chat__header__left">
                    <h4>ivory 811-01-100</h4>
                    <p style={{ color: 'grey', fontWeight: 500, fontSize: '14px' }}>Toch cost valley</p>
                </div>

                <div className="chat__header__right">
                    <Link style={{ display: 'flex' }} to="/archived">
                        <ArchiveOutlinedIcon style={{ color: 'grey', marginRight: '5px' }} fontSize="small" />  <p style={{ color: 'grey', fontSize: '14px', fontWeight: 500, margin: 0 }}>
                            Archive
                    </p>
                    </Link>
                </div>

            </div>
            {/* //CHATMESSEGES */}
            {/* MAP&LIST THE ROOMS MESSAGES */}
            <div className="chat__box">
                {messages.map((message, i) => (
                    <div key={i} className="chat__boxMsg">
                        <p className={`chat__message ${message.status === "received" && 'chat__reciever'}`} >
                            <span className={message.status === "delivered" ? "chat__name" : "chat__name--reciver"}> {message.from_number}</span>
                            {message.body}
                        </p>
                        <span className={message.status === "received" ? 'chat__timeStamp' : 'chat__timeStamp__reciver'}>12 sta </span>
                    </div>
                ))}
            </div>
            {/* //SENDBTNS%INPUT */}
            <form onSubmit={sendMessages} className="chat__box__send">
                <textarea onChange={handleChange('body')} className="chat_textarea" placeholder="Type..." />
                <div className="chat__box__sendBtnSection">
                    <div className="chat__box__template">
                        <input
                            accept="image/*"
                            style={{ display: 'none' }}
                            id="contained-button-file"
                            multiple
                            type="file"
                        />
                        <label style={{ display: 'flex' }} htmlFor="contained-button-file">
                            <AddIcon style={{ color: '#3f51b5' }} fontSize="small" />
                            <p>Template</p>
                        </label>
                    </div>
                    <div className="chat__box__icons">
                        <input style={{ display: 'none' }} id="icon-button-file" type="file" />
                        <label htmlFor="icon-button-file">
                            <IconButton color="primary" aria-label="upload picture" component="span">
                                <NoteIcon fontSize="small" />
                            </IconButton>
                        </label>

                        <button className="chat__sendbtn" type="submit">
                            <SendIcon style={{ marginRight: '3px' }} fontSize="small" /> Send
                            </button>
                    </div>
                </div>
            </form>
        </div >
    )
}

export default ChatBox

侧边栏组件:

import React, { useState, useEffect } from 'react'
import { createStyles, makeStyles, Theme, Button, TextField } from '@material-ui/core';
import CreateOutlinedIcon from '@material-ui/icons/CreateOutlined';
import SearchIcon from '@material-ui/icons/Search';
import Modal from '@material-ui/core/Modal';
import Backdrop from '@material-ui/core/Backdrop';
import Fade from '@material-ui/core/Fade';
import CloseIcon from '@material-ui/icons/Close';
import SendIcon from '@material-ui/icons/Send';
import './Sidebar.css'
import SidebarChat from './SidebarChat/SidebarChat'
import axios from 'axios'


const Sidebar = () => {
    //style func material-ui
    const classes = useStyles()
    //all the states to handle ui beahvious
    const [open, setOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [usersMessages, setUsersMessages] = useState<any[]>([]);
    const [usersList, setUsersLists] = useState<any[]>([]);
    // const [loading, setLoading] = useState(false);
    const [formInput, setFormInput] = useState<any>({
        to: '',
        body: ''
    })

    //destructure formData state
    const { to, body } = formInput;
    //POPULATES userLists state
    const getUsers = async () => {
        await axios.get(`http://206.189.138.105/api/sms/v1/sms-users`)
            .then((response) => {
                setUsersLists(response.data)
                // console.log(response.data)
            }).catch((err) => console.log(err)
            )
    }

    //FETCHING USER LIST ON FIRST RENDER & WHEN userList state changes it re-renders
    useEffect(() => {
        getUsers()
    }, [])


    //POPULATES userMessages state
    const getSms = async () => {
        await axios.get(`http://206.189.138.105/api/sms/v1/list-sms/+610466993589/`)
            .then((response) => {
                setUsersMessages(response.data)
                console.log(response.data)
            }).catch((err) => console.log(err)
            )
    }

    //FETCHING MESSAGES LIST ON FIRST RENDER & WHEN userList state changes it re-renders
    useEffect(() => {
        getSms()
    }, [])



    //HANDLE FORM INPUT CHANGES
    const handleChange = (name: any) => (event: any) => {
        setFormInput({
            ...formInput,
            [name]: event.target.value
        })
    }

    //CONVERT MESSAGE INPUT INTO FORM DATA TO SEND IN THE BAkCEND
    function getFormData(object: any) {
        const formData = new FormData();
        Object.keys(object).forEach(key => formData.append(key, object[key]));
        return formData;
    }


    //HANDLES FORM SUBMIT
    const handleSubmit = async (event: any) => {
        event.preventDefault()
        console.log('addnewmessage--clicked', getFormData(formInput));

        await axios.post('http://206.189.138.105/api/sms/v1/send-sms', getFormData(formInput))
            .then((response) => {
                setUsersMessages(response.data)
                console.log('addnewmsgInputs', response.data)
            }).catch((err) => console.log(err)
            )
    }

    // if (loading) {
    //     return (<h4>users loading...</h4>)
    // }

    //PREVENTS DEFUALT BEHAVIOUR LIKE LOADING
    const handleSearch = (event: any) => {
        event.preventDefault()
        // console.log('event');

    }

    //filters searched results
    const filteredUsers = usersMessages.filter(user => {
        return user.from_number.toLowerCase().includes(searchTerm.toLowerCase())
    })


    //MODAL OPEN AND CLOSE
    const handleOpen = () => {
        setOpen(true);
    };
    const handleClose = () => {
        setOpen(false);
    };

    return (
        <>
            <div className="sidebar">
                {/* HEADER */}
                <div className="sidebar__header">
                    <div onClick={handleOpen} className="sidebar__header__newMsg" >
                        <CreateOutlinedIcon style={{ color: "#4fab4a" }} fontSize="small" /> <h4 style={{ color: "#4fab4a" }} >New Message</h4>
                    </div>
                    {/* INPUT+SEARCH */}
                    <div onSubmit={handleSearch} className="search">
                        <form className="searchform" >
                            <input className={classes.input} type="text" value={searchTerm} onChange={(event) => setSearchTerm(event.target.value)} />
                            <SearchIcon fontSize="small" style={{ color: '#2167b9' }} />

                        </form>
                    </div>
                </div>
                {/* CHATS */}
                {/* map through searched resulst & displays it */}
                <div className={classes.sidebar__userList}>
                    {filteredUsers.map((item, i) => (
                        <SidebarChat key={i} item={item} />
                    ))}
                </div>
            </div>
            {/* MODAL TO GET DATA FOR NEW MESSAGE  */}
            <Modal
                aria-labelledby="transition-modal-title"
                aria-describedby="transition-modal-description"
                className={classes.modal}
                open={open}
                onClose={handleClose}
                closeAfterTransition
                BackdropComponent={Backdrop}
                BackdropProps={{
                    timeout: 500,
                }}
            >
                <Fade in={open}>
                    <div className={classes.paper}>
                        <div className={classes.close}>
                            <CloseIcon onClick={handleClose} />
                        </div>
                        <form onSubmit={handleSubmit} >
                            <h2 id="transition-modal-title">SEND MESSAGES</h2>
                            {/* <Input className="msginput" type="text" placeholder="Your Name.." /> */}
                            <input type="text" required value={to} onChange={handleChange('to')} className="msginput" placeholder="Your Number.." />
                            <TextField type="text" required value={body} onChange={handleChange('body')} variant="outlined" multiline placeholder="Your Message..." rows="5" fullWidth />
                            <div style={{ marginTop: '2rem' }}>
                                <Button variant="outlined" className="modal__btn" color='primary' type="submit"> <SendIcon style={{ marginRight: '3px' }} fontSize="small" />Send</Button>
                            </div>
                        </form>
                    </div>
                </Fade>
            </Modal>
        </>
    )
}

export default Sidebar

//CSS FOR MATERIAL UI COMPONENTS
const useStyles = makeStyles((theme: Theme) =>
    createStyles({
        sidebar__header__right: {
            '&>*': {
                marginLeft: '1rem'
            }
        },
        sidebar__userList: {
            flex: '1',
            overflowY: 'scroll'
        },
        modal: {
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            textAlign: 'center',

        },
        paper: {
            backgroundColor: theme.palette.background.paper,
            boxShadow: theme.shadows[5],
            padding: theme.spacing(2, 4, 3),
            width: '400px'
        },
        close: {
            display: 'flex',
            justifyContent: 'flex-end',
        },
        input: {
            border: 'none',
            width: '100%',
            height: '100%',
            borderRadious: '50px',
            fontSize: '18px',
            color: 'grey',
            fontWeight: 500,
        }
    }),
);

输出 enter image description here

0 个答案:

没有答案