How are messages sent slowly? I am using socket.io for sending messages but my app sending messages is working very slowly it almost takes 8-10 seconds on average to send messages how can I improve its performance? I tried using use callback but still is not sending messages fast what can i do to improve its performance?
const { otheruser } = route.params;
const [mydata, setMyData] = useState(null);
const [userid, setUserid] = useState(null);
const [roomid, setRoomid] = useState(null);
const [chat, setChat] = useState(['']);
const [currentmessage, setCurrentmessage] = useState(null);
useEffect(() => {
LoadData()
}, [])
useEffect(() => {
socket.on('receive_message', (data) => {
LoadMessages(roomid)
})
}, [socket])
const SortRoomId = (id1, id2) => {
if (id1 > id2) {
return id1 + id2
} else {
return id2 + id1
}
}
const LoadData = async () => {
try {
const value = await AsyncStorage.getItem('user');
const { token, user: { email } } = JSON.parse(value);
const res = await fetch('http://10.0.2.2:3000/userdata', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer' + token
},
body: JSON.stringify({ email })
});
const { message, user } = await res.json();
if (message === 'User Found') {
setMyData(user);
setUserid(user._id);
const ChatRoomId = await SortRoomId(otheruser[0]._id, user._id);
setRoomid(ChatRoomId);
socket.emit('joinroom', { roomid: ChatRoomId });
LoadMessages(ChatRoomId);
} else {
alert('Login Again');
navigation.navigate('Login');
}
} catch (err) {
navigation.navigate('Login');
}
};
const SendMessage = useCallback(async () => {
const MessageData = {
message: currentmessage,
RoomId: roomid,
SenderId: userid,
RecieverId: otheruser[0]._id
};
try {
const response = await fetch('http://10.0.2.2:3000/SaveMessage', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(MessageData)
});
const data = await response.json();
if (data.message === 'Message saved') {
socket.emit('sendmessage', MessageData);
LoadMessages(roomid);
console.log('message sent');
setCurrentmessage('');
} else {
alert('Network Error');
setCurrentmessage('');
}
} catch (error) {
console.error(error);
}
}, [currentmessage, roomid, userid, otheruser, socket]);
useEffect(() => {
LoadMessages(roomid)
}, [chat])
const LoadMessages = async (ChatRoomId) => {
try {
const res = await fetch('http://10.0.2.2:3000/GetMessages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ RoomId: ChatRoomId })
});
const data = await res.json();
setChat(data);
} catch (error) {
console.error(error);
}
}
Related
I was working on a project using Firebase cloud messaging react. I was sending this to my server, but it doesn't work. Surely I have tried, but I don't know what's wrong again.
Below is the code.
Here it sends a POST request to Firebase, and it should send a notification to the user.
async function sendNotification(id, userMessage) {
const headers = {
'Authorization': `key=${code}`,
'Content-Type': 'application/json'
}
const message = {
'to': `${id}`,
'content_available': true,
'apns_priority': 5,
'notification': {
body: `${userMessage}`
},
const url = 'https://fcm.googleapis.com/fcm/send'
//console.log(code)
await axios.post(url, message, {
headers: headers
})
}
const sendMessageToServer = async (e) => {
//e.preventDefault();
toggle()
const docRe = doc(database, "help", mailer);
const data = {
email: user.email,
user: newMessage,
}
//console.log(data, 'not clear')
setNewMessage('')
//console.log(data, newMessage, 'cleared')
setShow(false)
if(newMessage === '') {
}
else {
const docRef = doc(database, "users", mailer);
await updateDoc(docRe, {
msg: arrayUnion(data)
})
.then(() => {
async function p() {
const id = await getDoc(docRef)
//console.log(id.data())
sendNotification(id.data().notice, `Admin : ${data.user}`)
}
p()
})
}
Sometimes it sends to my localhost because I tested there, but it doesn't work on my Netlify app. Secondly, I noticed that it keeps generating the same token for each user, but that's not the issue, but if you can help in both I would be grateful.
export default function Dashboard() {
async function callToken() {
await getToken(messaging, {vapidKey: process.env.NOTIFICATION})
.then((code) => {
//console.log(code)
async function docRef() {
const dc = doc(database, "users", auth.currentUser.email);
await updateDoc(dc, {
notice: code
});
}
docRef()
})
}
async function requestPermission() {
await Notification.requestPermission()
.then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.')
callToken()
}
})
}
const goTo = useNavigate();
useEffect(() => {
onAuthStateChanged(auth, (data) => {
if(!data) {
goTo('/login')
}
else {
currentBalance();
requestPermission()
}
})
})
}
Please know I imported all required modules.
WARN Possible Unhandled Promise Rejection (id: 21): TypeError: undefined is not an object (evaluating 'res.json') How can I fix this problem in my code? I tried logging user and loggeduserobj both logs correctly but still, this error is coming I also logged the type of loggeduserobj it logs object Can you help me to fix this problem?
const { user } = route.params;
const [issameuser, setIssameuser] = useState(false)
const [follow, SetFollow] = useState(false)
const isMyProfile = async (otherprofile) => {
AsyncStorage.getItem('user').then((loggeduser) => {
const loggeduserobj = JSON.parse(loggeduser)
if (loggeduserobj.user.username == otherprofile[0].username) {
setIssameuser(true)
}
else {
setIssameuser(false)
}
})
}
const CheckFollow = async (otherprofile) => {
AsyncStorage.getItem('user')
.then(loggeduser => {
const loggeduserobj = JSON.parse(loggeduser);
fetch('http://10.0.2.2:3000/checkfollow', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
followfrom : loggeduserobj.user.username, followto: otherprofile[0].username
})
})
})
.then(res => res.json())
.then(data => {
if (data.message == "User in following list") {
SetFollow(true)
}
else if (data.message == "User not in following list") {
SetFollow(false)
}
else {
alert('Please Try Again!')
}
})
}
useEffect(() => {
isMyProfile(user)
CheckFollow(user)
}, [])
Backend:
router.post('/checkfollow', (req, res) => {
const { followfrom, followto } = req.body;
console.log(followfrom, followto);
if (!followfrom || !followto) {
return res.status(422).json({ error: "Invalid Credentials" });
}
User.findOne({ username: followfrom })
.then(mainuser => {
if (!mainuser) {
return res.status(422).json({ error: "Invalid Credentials" });
}
else {
let data = mainuser.following.includes(followto);
console.log(data);
if (data == true) {
res.status(200).send({
message: "User in following list"
})
}
else {
res.status(200).send({
message: "User not in following list"
})
}
}
})
.catch(err => {
return res.status(422).json({ error: "Server Error" });
})
})
You need to return a Promise, the result of fetch, from your first .then() so that it can be chained on, like so:
const CheckFollow = async (otherprofile) => {
AsyncStorage.getItem('user')
.then(loggeduser => {
const loggeduserobj = JSON.parse(loggeduser);
return fetch('http://10.0.2.2:3000/checkfollow', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
followfrom : loggeduserobj.user.username, followto: otherprofile[0].username
})
})
})
.then(res => res.json())
.then(data => {
if (data.message == "User in following list") {
SetFollow(true)
} else if (data.message == "User not in following list") {
SetFollow(false)
} else {
alert('Please Try Again!')
}
})
}
You should also consider using await in this case, especially since your function is already marked as async to make things more readable
const CheckFollow = async (otherprofile) => {
const loggeduser = await AsyncStorage.getItem('user');
const loggeduserobj = JSON.parse(loggeduser);
const res = await fetch('http://10.0.2.2:3000/checkfollow', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
followfrom : loggeduserobj.user.username, followto: otherprofile[0].username
})
});
const data = await res.json();
if (data.message == "User in following list") {
SetFollow(true)
} else if (data.message == "User not in following list") {
SetFollow(false)
} else {
alert('Please Try Again!')
}
}
How To Refresh User data coming from a variable route? I have a variable called "user" which is coming from a different screen by "react navigation" route that user variable contains all the data I need, So How can I reload that user variable data after "Set follow" is true without fetching anything because "user" variable data is coming is fetching from a different screen?
Code:
const Profile = ({ navigation, route }) => {
const { user } = route.params; // HERE IS THAT USER VAR
const [issameuser, setIssameuser] = useState(false)
const [follow, SetFollow] = useState(false)
const isMyProfile = async (otherprofile) => {
AsyncStorage.getItem('user').then((loggeduser) => {
const loggeduserobj = JSON.parse(loggeduser)
if (loggeduserobj.user.username == otherprofile[0].username) {
setIssameuser(true)
}
else {
setIssameuser(false)
}
})
}
const CheckFollow = async (otherprofile) => {
AsyncStorage.getItem('user')
.then(loggeduser => {
const loggeduserobj = JSON.parse(loggeduser);
return fetch('http://10.0.2.2:3000/checkfollow', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
followfrom: loggeduserobj.user.username, followto: otherprofile[0].username
})
})
})
.then(res => res.json())
.then(data => {
if (data.message == "User in following list") {
SetFollow(true)
} else if (data.message == "User not in following list") {
SetFollow(false)
} else {
alert('Please Try Again!')
}
})
}
const FollowUser = async (otherprofile) => {
const loggeduser = await AsyncStorage.getItem('user')
const loggeduserobj = JSON.parse(loggeduser)
fetch('http://10.0.2.2:3000/Follow', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
followfrom: loggeduserobj.user.username, followto: otherprofile[0].username
})
})
.then(res => res.json())
.then(data => {
if (data.message == "User Followed") {
SetFollow(true) // HERE I WANT TO RE-LOAD USER VAR DATA
}
else {
alert("Pleas Try Again")
}
})
}
useEffect(() => {
isMyProfile(user)
CheckFollow(user)
},)
}
is their any method to do that or i need to use socketio?
i have created a asyncthunk, but when status code is 400, the result of request is still fulfilled, which method is to handle a 400 error with createasyncthunk and fetch api?
This is a action code:
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import authService from "./auth-service";
// Get user from localStorage
const user = JSON.parse(localStorage.getItem("user"));
const initialState = {
user: user ? user : "",
isError: false,
isSuccess: false,
isLoading: false,
message: "",
};
// Register user
export const register = createAsyncThunk(
"auth/signup",
async (user, thunkAPI) => {
try {
return await authService.register(user);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
// Login user
export const login = createAsyncThunk("auth/login", async (user, thunkAPI) => {
try {
return await authService.login(user);
} catch (error) {
const message =
(error.response && error.response.data && error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
});
export const logout = createAsyncThunk("auth/logout", async () => {
await authService.logout();
});
export const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
reset: (state) => {
state.isLoading = false;
state.isSuccess = false;
state.isError = false;
state.message = "";
},
},
extraReducers: (builder) => {
builder
.addCase(register.pending, (state) => {
state.isLoading = true;
})
.addCase(register.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.isSuccess = false;
state.user = "";
})
.addCase(register.fulfilled, (state, action) => {
state.isLoading = false;
state.isError = false;
state.isSuccess = true;
state.message = action.payload;
})
.addCase(login.pending, (state) => {
state.isLoading = true;
})
.addCase(login.fulfilled, (state, action) => {
state.isLoading = false;
state.isSuccess = true;
state.user = action.payload;
})
.addCase(login.rejected, (state, action) => {
state.isLoading = false;
state.isError = true;
state.message = action.payload;
state.user = "";
})
.addCase(logout.fulfilled, (state) => {
state.user = "";
});
},
});
export const { reset } = authSlice.actions;
export default authSlice.reducer;
This is a service code:
import React from 'react'
import Cookies from 'js-cookie'
const API_URL = "http://localhost:5000/api/auth/";
const token = Cookies.get('XSRF-Token')
// Register user
const register = async (userData) => {
const response = await fetch(API_URL + "signup", {
method: "POST",
credentials: 'include',
headers: {
'X-CSRF-Token': token,
'Accept': "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(userData),
});
const responseData = await response.json();
if (response.ok) {
localStorage.setItem("user", JSON.stringify(responseData));
return responseData;
}
};
// Login user
const login = async (userData) => {
const response = await fetch(API_URL + "login", {
method: "POST",
credentials: 'include',
body: JSON.stringify(userData),
headers: {
'X-CSRF-Token': token,
'Accept': "application/json",
"Content-Type": "application/json",
},
});
const responseData = await response.json();
if (response.ok) {
localStorage.setItem("user", JSON.stringify(responseData));
return responseData;
}
};
// Logout user
const logout = () => {
localStorage.removeItem("user");
};
const authService = {
register,
logout,
login,
};
export default authService;
The problem is both register and login action, return a fulfilled even if the code of post request is 400 and my intention is send a message about error
Your code doesn't do anything if response.ok is not truthy. That's what will happen when you get a 4xx status.
So, for example, in this code:
// Register user
const register = async (userData) => {
const response = await fetch(API_URL + "signup", {
method: "POST",
credentials: 'include',
headers: {
'X-CSRF-Token': token,
'Accept': "application/json",
"Content-Type": "application/json",
},
// body: JSON.stringify(userData),
});
const responseData = await response.json();
if (response.ok) {
localStorage.setItem("user", JSON.stringify(responseData));
return responseData;
}
};
You just allow the async function to have an undefined return value if response.ok is not truthy. That will resolve the promise, with an undefined resolved value.
Perhaps, you want to turn any non-2xx status into a rejection like this:
// Register user
const register = async (userData) => {
const response = await fetch(API_URL + "signup", {
method: "POST",
credentials: 'include',
headers: {
'X-CSRF-Token': token,
'Accept': "application/json",
"Content-Type": "application/json",
},
// body: JSON.stringify(userData),
});
if (response.ok) {
const responseData = await response.json();
localStorage.setItem("user", JSON.stringify(responseData));
} else {
// reject the promise
throw new Error(`status code ${response.status}`)
}
};
You would probably want to do something similar for all your uses of fetch().
Since I find that I want this to be the standard behavior when making requests, I have my own fetchWrapper() function that automatically converts any non-2xx status to a promise rejection so I don't have to code that into every use of fetch().
Here's an example of a fetchWrapper function that turns any http status that is not in the range of 200-299 into a rejected promise:
async function fetchJSON(url, options) {
let response = await fetch(url, options);
if (!response.ok) {
throw new Error(`status code ${response.status}`);
}
return response.json();
}
I'm having a problem with my API request that always fails after page load. Don't really know where Im wrong.
Here's my request and I call it when I interact with handleOpen function.
const stock = {
method: 'GET',
url: 'https://morningstar1.p.rapidapi.com/live-stocks/GetRawRealtimeFigures',
params: {Mic: props.mic, Ticker: clickedElement.ticker},
headers: {
'x-rapidapi-key': 'XXX',
'x-rapidapi-host': 'morningstar1.p.rapidapi.com'
}
}
const getStock = async () => {
try {
const res = await axios.request(stock);
return res.data;
}
catch (error) {
setOpen(false);
console.error("catch api error: ", error);
}
}
const handleOpen = name => {
let findClickedStock = props.stocksArray.find(item => item.ticker === name)
setClickedElement(findClickedStock)
getStock().then((dataFromStockApi) => {
let combined1 = { ...dataFromStockApi, ...findClickedStock }
setStockObject(combined1);
});
setOpen(true);
};
ERROR:
It's because your Ticker parameter is empty.
When you create "stock", clickedElement.ticker is undefined.
Do this:
// pass name in as a parameter
getStock(name).then(...)
Make getStock like like this:
const getStock = async (ticker) => {
try {
const res = await axios.request({
method: 'GET',
url: 'https://morningstar1.p.rapidapi.com/live-stocks/GetRawRealtimeFigures',
params: {Mic: props.mic, Ticker: ticker},
headers: {
'x-rapidapi-key': 'XXX',
'x-rapidapi-host': 'morningstar1.p.rapidapi.com'
}
});
return res.data;
}
catch (error) {
setOpen(false);
console.error("catch api error: ", error);
}
}