Problems using React JS and WebSockets - node.js

I am learning about these technologies (React JS, Node, WebSockets) and working on a project that uses websockets to display information on graphs in real time.
I have a state in my component that stores an array of objects with different attributes.
When I make a POST request to my server the record is saved in the database (Made in PostgreSQL) and I notify the client to do the update
My problem is that when I refresh the page it stops working and I need to restart the server to be able to see the changes in the graph again.
SERVER
io.on('connection', client => {
app.post("/registros/nuevo", async (req, res) => {
try {
let insertar = await pool.query(`INSERT INTO registro
(fecha, hora, temperatura, presion, humedad, viento, viento_max, radiacion, precipitacion)
VALUES
('${req.body.fecha}', '${req.body.hora}', ${req.body.temperatura}, ${req.body.presion},
${req.body.humedad}, ${req.body.viento}, ${req.body.viento_max}, ${req.body.radiacion},
${req.body.precipitacion});`).then(() => { client.emit('new: data', 'updated') });
res.json({ message: "Recibido" });
} catch (err) {
console.error(err.message);
}
});
});
CLIENT
const [data, setData] = useState([])
const getData = async () => {
try {
const response = await fetch("http://localhost:5000/registros");
const jsonData = await response.json();
setData(jsonData);
setCurrent(jsonData[jsonData.length - 1])
} catch (err) {
console.error(err.message)
}
};
useEffect(() => {
getData()
}, [])
useEffect(() =>{
socket.on('new: data', (c) =>{
console.log(c)
getData()
})
}, []);
I know that my code isn't the best, and thank u for ur help

I got the solution, my mistake was put the request inside of socket body
app.post("/registros/nuevo", async (req, res) => {
try {
let insertar = await pool.query(`INSERT INTO registro
(fecha, hora, temperatura, presion, humedad, viento, viento_max, radiacion, precipitacion)
VALUES
('${req.body.fecha}', '${req.body.hora}', ${req.body.temperatura}, ${req.body.presion}, ${req.body.humedad}, ${req.body.viento}, ${req.body.viento_max}, ${req.body.radiacion}, ${req.body.precipitacion});`)
io.emit('new: data', 'Actualizado')
res.sendStatus(204)
} catch (err) {
res.sendStatus(500)
}
});

Related

Api works only on localhost

on my machine i get a json response when i consume my api and eveything is working fine , but the weird thing is my api not giving me data when i upload it online , i am using namecheap shared hosting , this is the result i get when try to consume api
this is my index.js code
app.get("/project/index/login", (req, res) => { (async () => {
try {
await client.login();
res.send("Login successful!");
} catch (err) {
res.send("Login failed!");
} })(); });
app.get("/project/index/user/:id", (req, res) => {
const id = req.params.id; (async () => {
try{
const data = await client.getInfo({ id: id })
res.json(data.data);
}catch(error){
res.send(error);
}
})(); });
app.listen(port, () => {
console.log(`Listening on port http://localhost:${port}...`);
});
It's probably because your API server is running only on localhost. Check your API server!. You must run the API server which has a domain.

Empty row on MongoDB data insertion using express.js

I want to add data to my MongoDB collection. I'm getting this data via a local Flask API. I'm GETting the data on my React Frontend and it's displaying fine. I'm not sure why I can't do the same thing on my express nodejs backend. I want to get that same data and use it to build the entity that I'm going to store.
This is how I'm attempting to get the data
app.get('/', async (req, res) => {
let initialData = {};
axios.get('http://localhost:3000/details').then((res) => {
initialData = res.data;
});
const recruit = new RecruitModel({ email:initialData.email,
mobile_number:initialData.mobile_number,
name:initialData.name});
try {
await recruit.save()
res.send("inserted data")
} catch (error) {
console.log(error)
}
})
I'm pretty sure something wrong there and nowhere else. Because if I pass static information instead it's correctly stored, no issues.
You are saving to the database's Recruit Collection before the promise is resolved. Since data to save in the Recruit Collection is dependent upon the result from the API which will initially return the promise, therefore, use promise resolving functions to wait for its result.
Solution#1 (using .then function):
app.get('/', async (req, res) => {
let initialData = {};
try {
axios.get('http://localhost:3000/details').then((response) => {
initialData = response.data;
const recruit = new RecruitModel({
email: initialData.email,
mobile_number: initialData.mobile_number,
name: initialData.name,
});
recruit.save().then((response) => res.send('inserted data'));
});
} catch (error) {
console.log(error);
}
});
Solution#2 (using async await keywords):
app.get('/', async (req, res) => {
try {
const response = await axios.get('http://localhost:3000/details');
const recruit = new RecruitModel({
email: response.data.email,
mobile_number: response.data.mobile_number,
name: response.data.name,
});
await recruit.save();
res.send('inserted data');
} catch (error) {
console.log(error);
}
});
Either solution will work in your case.

Hide api using expressjs and react

I'm using MERN stack for a project. I want to hide my api endpoints on the frontend when I call them. I'm now making a request from React like so:
useEffect(() => {
axios
.get("https://MY_API_URL/posts") // MY_API_URL is the url that I want to hide
.then((res) => {
dispatch(setCurrentUser(res.data));
})
.catch((err) => {
console.log(err);
});
});
This is how I'm GETing the posts from the expressjs:
controllers/posts.js
const Post = require("../models/post");
const getPosts = async (req, res) => {
try {
const post = await Post.find();
res.status(200).json(post);
} catch (err) {
res.status(404).json({ message: err });
}
};
I want to make the request to the url from the backend so that my API is hidden in the client.
This is what I have tried in the frontend:
useEffect(() => {
axios
.get("http://localhost:3000/posts")
.then((res) => {
dispatch(setCurrentUser(res.data));
})
.catch((err) => {
console.log(err);
});
});
And my backend now looks like this but it doesn't work. I also have removed the Posts.find() inside the request, I'm not sure if it is still necessary or how am I going to use this?
controllers/posts.js
const getPosts = async (req, res) => {
try {
const response = await axios.get(
"https://MY_API_URL/posts"
);
const posts = response.data;
console.log(posts);
res.status(200).json(posts);
} catch (err) {
res.status(404).json({ message: err });
}
};
On localhost it works fine, but when I push my code to github and deploy it, it doesn't work on the deployed version then in the localhost it also stops working.
Error message on console:
GET http://localhost:3000/posts 404 (Not Found)

multiple async-await get requests not working in PERN stack app

I'm working on building an inventory management application using PERN stack. I have a modal where I need to make 2 GET requests and when I console.log in front end both requests are getting Status 200 response. However in my express server, first get request is working fine but the second request is not receiving anything.
My frontend code
const openModal = async () => {
setDetailModalOpen(true)
try {
await Promise.all([
(async () => {
const serial_number = props.bacsSerial
const response = await fetch(`http://localhost:5000/bacslist/demoinventory/${serial_number}`)
const parseResponse = await response.json()
console.log(response)
setInputs({
bacsUnit: parseResponse.bacs_unit,
serialNumber: parseResponse.serial_number,
partNumber: parseResponse.part_number,
bacsLocation: parseResponse.bacs_location,
description: parseResponse.bacs_description
})
setBacsId(parseResponse.id)
setBacsData(parseResponse)
})(),
(async () => {
const response2 = await fetch(`http://localhost:5000/bacslist/demoinventory/${bacsId}`)
console.log(response2)
})()
])
} catch (err) {
console.error(err.message)
}
}
My backend code
router.get("/demoinventory/:serial_number", async (req, res) => {
console.log('This one is working')
try {
const {serial_number} = req.params
const getDemoBacs = await pool.query(
"SELECT * FROM demo_inventory WHERE serial_number = $1", [serial_number]
)
res.json(getDemoBacs.rows[0])
} catch (err) {
console.error(err.message)
}
})
router.get("/demoinventory/:bacsId", async (req, res) => {
console.log(req.params)
console.log('This one is not working')
try {
const getHistoryData = await pool.query(
"SELECT * FROM demo_inventory_history"
)
console.log(getHistoryData)
res.json(getHistoryData)
} catch (err) {
console.error(err.message)
}
})
Sorry, Kinda new to this stuff so this isn't exactly an answer but I'm not allowed to leave a comment. I can't see your state variables with the code you posted, but are you sure that BacsId is being set to state before it is used in the second call, or is the parameter in the second call being sent empty, thus not using the right URL? Just a thought.

How to make a realtime crud using vuex and socketio?

I want to perform a realtime crud using vuex, node, express and socketio but using the following syntax I can't get the result.
Server
index.js
const server = app.listen('3000',() => {
console.log('<--- Web Server Starter --->')
const io = require('./sockets')(server)
io.on('connection', socket=>{
console.log('client connected');
})
})
socket.js
let io
module.exports = {
init:httpServer =>{
io = require('socket.io')(httpServer)
return io
},
getIo:()=>{
if(!io){
throw new Error('socket io not initialized')
}
return io
}
}
user.js
const io = require('../socket')
router.post('/newuser',(req, res) => {
res.json({ serverResponse: 'userCreated' })
io.getIo().emit('newuser',{serverResponse:'created',user:user})
})
Client
Module user.js (VUEX actions)
getusers({ commit }){
const sessionToken = localStorage.getItem('sessionToken')
axios.get('/newuser', {
headers: {
Authorization: `Bearer ${localStorage.getItem('sessionToken')}`
},
})
.then(response => {
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
if (data.serverResponse === 'created') {
this.users = data.user
commit('GET_USERS', users)
})
})
.catch(error => {
alert(error)
})
})
When I create the new user, the user list is not updated automatically, but I have to refresh the page to see the new user, why does this happen?
This is because in your backend you are handling the post url-endpoint '/newuser' to get the data. You are not actually posting the data using socketio, therefore if you don't update the page, your axios.get function isn't going to have any new data to get until the API you are posting to has refreshed. It would be better to put your socket client code outside of the axios promise so that the data is primarily updated on the client by socketio and not by the API.
EDIT:
This is the code for it in your client
getusers({
commit
}) {
const sessionToken = localStorage.getItem('sessionToken')
axios.get('/newuser', {
headers: {
Authorization: `Bearer ${localStorage.getItem('sessionToken')}`
},
})
.then(response => {
console.log('success');
})
.catch(error => {
alert(error)
})
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
if (data.serverResponse === 'created') {
this.users = data.user
commit('GET_USERS', users)
})
})
You had a problem with your .catch part of the promise as it was inside the .then part and I also moved your socket code outside of the promise.
So in your server when you post to /newuser. you send emit from the socketio
on your client you dont need to use axios to check if some socket events has been fired, try to remove the axios.get() and keep
const socket = openSocket('http://localhost:3000')
socket.on('newuser', data => {
//do some thing
})

Resources