聊天应用程序如何知道用户何时发送消息以重新呈现?
Posted
技术标签:
【中文标题】聊天应用程序如何知道用户何时发送消息以重新呈现?【英文标题】:How do chat apps know when a user sends a message to re render? 【发布时间】:2021-06-27 01:30:47 【问题描述】:我需要使用 websockets 吗?我正在使用 mysql 创建一个反应应用程序,我希望它基本上是一个聊天应用程序。我可以让它在我正在使用的浏览器中重新呈现,但是如果我打开另一个选项卡并输入一条消息,我的应用程序将不会重新呈现。有什么简单的方法可以解决这个问题还是我应该使用 websockets?这是我的代码。
app.js
useEffect(() =>
console.log('use effect is in use.');
fetch(`http://localhost:4000/getallmessages`)
.then((data) => data.json())
.then((messages) =>
setGetAllMessages(messages);
)
.catch((err) =>
console.log(err);
);
, []);
return (
<div className=classes.AppContainer>
loggedIn ? (
<>
loginMessage ? setIntervalMessage() : null
loginMessage ? (
<h3 className=classes.SuccessMessage>
loginMessage.successMessage
</h3>
) : null
<Chatroom
user=user
getAllMessages=getAllMessages
setGetAllMessages=setGetAllMessages
/>
</>
) : (
<>
<Login
setSignInPassword=setSignInPassword
setSignInUsername=setSignInUsername
login=login
signInPassword=signInPassword
signInUsername=signInUsername
/>
loginErrorMessage ? (
<p className=classes.ErrorMessage>
loginErrorMessage.errorMessage
</p>
) : null
<Signup
setUsername=setUsername
setPassword=setPassword
createUsername=createUsername
username=username
password=password
/>
signup ? <p>signup.message</p> : null
signupError ? <p>signupError.errors[0].msg</p> : <p></p>
</>
)
</div>
);
;
这里是聊天室组件
const Chatroom = ( user, getAllMessages, setGetAllMessages ) =>
const [getMessages, setGetMessages] = useState();
const [userMessage, setUserMessage] = useState('');
const [getAllUsers, setGetAllUsers] = useState();
const [flag, setFlag] = useState(false);
const [randomColor, setRandomColor] = useState(
Math.floor(Math.random() * 16777215).toString(16)
);
const messagesEndRef = useRef(null);
const scrollToBottom = () =>
messagesEndRef.current?.scrollIntoView( behavior: 'smooth' );
;
useEffect(() =>
fetch(`http://localhost:4000/getallusers`)
.then((data) => data.json())
.then((users) =>
console.log('-----ALL USERS------', users);
setGetAllUsers(users);
)
.catch((err) => console.log(err));
, []);
useEffect(() =>
fetch(`http://localhost:4000/getuser/$user.username/$user.id`)
.then((response) => response.json())
.then((data) =>
setGetMessages(data.message);
)
.catch((err) =>
console.log(err);
);
, []);
const sendMessage = (e) =>
setUserMessage('');
e.preventDefault();
const body =
userMessage: userMessage,
user: user.username,
userId: user.id,
;
fetch(`http://localhost:4000/sendmessage/$user.id`,
method: 'POST',
headers:
'Content-Type': 'application/json',
,
body: JSON.stringify(body),
)
.then((data) =>
return data.json();
)
.then((message) =>
console.log('success', message);
setFlag(true);
)
.catch((err) =>
console.log(err);
);
;
const getUserInput = (e) =>
setUserMessage(e.target.value);
;
useEffect(() =>
if (flag === true);
fetch(`http://localhost:4000/getallmessages`)
.then((data) => data.json())
.then((messages) =>
setGetAllMessages(messages);
setFlag(false);
)
.catch((err) =>
console.log(err);
);
, [flag]);
useEffect(() =>
scrollToBottom();
, [getAllMessages, flag]);
if (
user === undefined ||
getMessages === undefined ||
getAllMessages === undefined ||
getAllUsers === undefined
)
return <p>loading..</p>;
return (
<div className=classes.ChatroomContainer>
<h1>Welcome user ? user.username : 'Elita'</h1>
<div className=classes.ChatroomBox>
getAllMessages.message.map((allMessages) => (
<div key=allMessages.id>
<p>
getAllUsers.messages.map((user) =>
user.id === allMessages.userId ? (
<span
key=user.id
className=classes.UsernameColor
//create a random color to differenciate users.
style=
color: '#' + randomColor,
>
user.username :
</span>
) : (
''
)
)
allMessages.message
</p>
<div ref=messagesEndRef />
</div>
))
<input type='hidden' name=user ? user.username : '' />
<input type='hidden' name=user ? user.id : '' />
</div>
<div className=classes.SendMessageUI>
<input
type='text'
name='userMessage'
placeholder='hi eli ;)'
onChange=(e) => getUserInput(e)
onKeyDownCapture=(e) => (e.keyCode === 13 ? sendMessage(e) : null)
value=userMessage
></input>
<button onClick=sendMessage>Send</button>
</div>
</div>
);
;
最后用 node.js 做后端
路线
router.get('/getallusers', chatroomController.getAllUsers);
router.get('/getallmessages', chatroomController.getAllMesssages);
router.get('/getuser/:user/:userid', chatroomController.getUser);
router.post(
'/createuser',
body('username')
.isLength( min: 3 )
.withMessage('oops username must be at least 3 characters in length'),
body('password')
.isLength( min: 5 )
.withMessage('oops password must have 5 characters'),
authController.createUser
);
router.post(
'/signin',
body('signInUsername')
.isLength( min: 3 )
.withMessage('oops username needs at least 5 characters'),
body('signInPassword')
.isLength( min: 5 )
.withMessage('oops password needs to be at least 5 characters'),
authController.postSignin
);
router.post('/sendmessage/:userid', chatroomController.postSendMessage);
和控制器
exports.getAllUsers = async (req, res, next) =>
User.findAll()
.then((user) =>
if (!user)
res.json( message: 'oops no users' );
return next();
res.json( messages: user );
console.log(user);
)
.catch((err) =>
console.log(err);
);
;
exports.getAllMesssages = (req, res, next) =>
Message.findAll()
.then((messages) =>
if (!messages)
console.log('oops no messages');
res.json( message: 'oops no messages' );
return next();
console.log(messages);
res.json( message: messages );
)
.catch((err) =>
console.log(err);
);
;
exports.getUser = (req, res, next) =>
Message.findAll( where: userId: req.params.userid )
.then((userAndMessage) =>
if (!userAndMessage)
res.json( message: 'oops something went wrong.' );
return next();
console.log(userAndMessage);
res.json( message: userAndMessage, user: userAndMessage );
)
.catch((err) =>
console.log(err);
return err;
);
;
exports.postSendMessage = (req, res, next) =>
const message = req.body.userMessage;
const userId = req.params.userid;
console.log(req.params);
Message.create(
message: message,
userId: userId,
)
.then((message) =>
console.log(message);
res.json( message: 'success!', message: message );
)
.catch((err) =>
console.log(err);
res.json( message: 'something went wrong.' );
);
;
【问题讨论】:
【参考方案1】:我建议使用 Web 套接字或 MQTT,使用 MQTT,您需要连接到像 Mosquitto 或 CloudMQTT 这样的代理才能订阅主题。然后,您可以在 React 应用程序中实现逻辑以在消息到达时更新状态,这将导致页面重新呈现。如果您采用这种方法并设置客户端,我会选择Paho。
这里有一个sn-p给你一个想法:
const [message, setMessage] = useState("");
const client = new Paho.MQTT.Client(location.hostname, Number(location.port), "clientId");
// set callback handlers
client.onMessageArrived = onMessageArrived;
// called when a message arrives
const onMessageArrived = (message) =>
setMessage(message.payloadstring);
【讨论】:
以上是关于聊天应用程序如何知道用户何时发送消息以重新呈现?的主要内容,如果未能解决你的问题,请参考以下文章
关闭了5G消息,还能使用聊天机器人(Chatbot)吗?给聊天机器人(Chatbot)发短信是不是会