我需要使用 websockets 吗?我正在使用 MySQL 创建一个 React 应用程序,我希望它基本上是一个聊天应用程序。我可以让它在我使用的浏览器中重新呈现,但如果我打开另一个选项卡并输入一条消息,我的应用程序将不会重新呈现。有什么简单的方法可以解决这个问题,或者我应该使用 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.' });
});
};
答案 0 :(得分:0)
我建议使用网络套接字或 MQTT,通过 MQTT,您需要连接到像 Mosquitto 或 CloudMQTT 这样的代理才能订阅主题。然后,您可以在 React 应用程序中实现逻辑以在消息到达时更新状态,这将导致页面重新呈现。如果您采用这种方法并建立客户,我会选择Paho。
这是一个给你一个想法的片段:
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);
}