Unable to fetch data from MySQL database with Fetch API - javascript

I'm able to post successfully to MySQL database with Fetch API. The problem I'm having is trying to retrieve data from my database.
client.js:
const output = document.getElementById('output');
const username = document.querySelector('#username');
const date = document.querySelector('#date');
const submitbtn = document.querySelector('#submitbtn');
const commentOutput = document.querySelector('#message');
const form = document.querySelector('#form');
const comments = document.getElementById('message')
form.addEventListener('submit', function(e) {
e.preventDefault(e);
sendMessage();
let formMessage = new FormData(form);
formMessage.append('api-key', 'myApiKey');
fetch('http://localhost:5502/superhero', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({ comments: comments.value })
}).then(function(response) {
console.log(response)
console.log(JSON.stringify({ comments: comments.value }))
return response.json()
}).then(function(data) {
console.log(data);
}).catch(function(error) {
console.log(error);
});
})
submitbtn.addEventListener('click', function() {
fetch('http://localhost:5502')
.then(response => {
if (response.ok) {
console.log('success')
} else {
console.log('failure')
}
return response.json();
})
.then(data =>
console.log(data))
.catch(error => console.log('Error'))
var newUser = document.createElement("div");
var newName = document.createElement("h5");
var newDate = document.createElement("h5");
var newMessage = document.createElement("h6");
newName.textContent = comments.value;
newDate.textContent = message.value;
newMessage.textContent = message.value;
output.appendChild(newName);
output.appendChild(newDate);
output.appendChild(newMessage);
output.appendChild(newUser);
})
The problem here is the fetch method under the submitbtn:
Output:
index.js:
router.post("/superhero", function(req, res) {
const user = req.user;
const comments = req.body.comments;
sqlDatabase.query("INSERT INTO comments (user_id, comments) VALUES (?, ?)", [user, comments],
function(error, results, fields) {
console.log(results);
console.log(comments);
console.log('This is: ', comments)
console.log(error)
if (error) throw error;
});
})
router.get("/superhero", authenticationMiddleware(), function(req, res, err) {
sqlDatabase.query("SELECT users.username, comments.comments, comments.date FROM users INNER JOIN comments ON users.user_id=comments.user_id",
function(error, results, fields) {
if (error) throw error;
console.log(results);
console.log(error);
res.render('superhero');
})
})
I want to retrieve that data under router.get
Hope this is enough details. Thanks in advance. Noob by the way.

The res.send actually send back the JSON response
router.get("/superhero", authenticationMiddleware(), function(req, res, err) {
sqlDatabase.query("SELECT users.username, comments.comments, comments.date FROM users INNER JOIN comments ON users.user_id=comments.user_id",
function(error, results, fields) {
if (error) throw error;
console.log(results);
console.log(error);
res.send({heros: results}); //<-- send back the JSON response
})
})
Also, you can add condition if you're rendering on the server side as well
if (req.accepts('json')) {
res.send({hero: 'superhero'}); // <-- try sending back JSON object but rather a string
// OR
res.send({heros: results});
else {
res.render('superhero');
}
If you're using Express then you can use response.json method as well.

Finally got the results I wanted. I just created another api for retrieving data from my server file and changed
this:
fetch('http://localhost:5502/superhero')
to:
fetch('http://localhost:5502' + '/get_messages')
app.get("/get_messages", function(request, result) {
sqlDatabase.query("SELECT users.username, comments.comments, comments.date FROM users INNER JOIN comments ON users.user_id=comments.user_id",
function(error, results) {
result.end(JSON.stringify(results));
console.log(results);
});
});
So I have a route for rendering a view, and one for retrieving the data

Related

How to get response from a dynamic amount of URL's and combine JSON response from all of them

Currently I have a small JSON file with a list of URL's to fetch data from, this amount can change at any time, so I have built a small function to request from the URL's and log a JSON response from each of them, but currently I need to combine the responses from all of them and send them in a res.json format.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
var o1 = response.data
var obj = Object.assign(o1);
console.log(obj)
//res.json(obj.data);
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I was thinking that the code would look something like this (Pseudo code)
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
dynamic(var)object
databases.find({}, function(err, docs) {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
axios.post(url, req.body)
.then(function(response) {
add(response) to (var) object
})
.catch(function(error) {
console.log(error)
res.json({ success: false });
});
}
when function is finished (console.log[(var)]) with added JSON from all of the requests
});
} catch {
console.log(error)
res.json({ success: false });
}
});
I have seen solutions where the existing JSON data is overwritten if both the Response and JSON Object have the same value, and I want to avoid that.
I have tried storing the response data inside a var, but it would get overwritten if the data inside the var and the response had the same value.
I have also tried adding them together separately, but that makes numerous arrays, and I don't want that.
How you combine the json responses received completely depends on the information content of the response json. You can combine the responses as shown below or write custom logic to combine the jsons depending on actual responses and send the result.
app.post('/api/:db/find', async (req, res) => {
try {
const db = req.params.db;
const JsonAggreagate = []
databases.find({}, async function(err, docs) {
try {
for (const val of docs) {
var url = val.url + "/" + db + "/findmany"
let result = await axios.post(url, req.body)
//LOGIC FOR COMBINING JSON RESPONSES
JsonAggreagate.push({url: url, result : result})
}
} catch (error) {
console.log(error)
res.json({ success: false });
}
//when function is finished (console.log[(var)]) with added JSON from all of the requests
res.json({ success: true, result : JsonAggreagate});
});
} catch {
console.log(error)
res.json({ success: false });
}
});

How to send x-www-form-urlencoded with axis?

here is the screen shot of working postman form type.
As you can see I am posting x-www-form-urlencoded data back.
So I search google and found multiple posts about how to send this data back with axios.
In my login screen, I have something like this.
const handleLogin = values => {
setLoading(true);
const params = new URLSearchParams();
params.append('username', values.username);
params.append('password', values.password);
params.append('grant_type', 'password');
dispatch(fetchToken(params))
.then(res => {
navigation.navigate('Home', {screen: 'HomePage'});
})
};
In my redux, I have something like this.
export function fetchToken(params) {
return async dispatch => {
function onSuccess(response) {
tokenData = response.data.Token;
dispatch({type: LOGGED_IN, payload: response.data});
return response;
}
try {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
console.log(params)
const response = await axios.post('/token', params, config);
await AsyncStorage.setItem('token_local', JSON.stringify(response.data));
return onSuccess(response);
} catch (error) {
alert('Provided username and password is incorrect');
throw Error(error);
}
};
}
The thing is that I always get into catch error here. Even the username and password are the same. What am I doing wrong

I can't insert data to my database (mysql)

I'm learning now MySQL and I have a some problem. I tried to make a post request to my db::
My code from client side:
async function sendValues() {
const settings = {
method: 'post',
headers: { "Content-Type": "application/json" },
body: JSON.stringify(product)
}
try {
const fetchResponse = await fetch('http://localhost:9001/products', settings);
const data = await fetchResponse.json();
console.log(data) // what the user send
} catch (err) {
return err
}
}
My code from server side:
router.post('/', (req, res) => {
const { c_id, p_name, p_price } = req.body
const q =
`
INSERT INTO products (c_id,p_name,p_price)
VALUES("${c_id}", "${p_name}" , "${p_price}")
`;
con.query(q, (err, result, fields) => {
if (err) throw err;
res.json(result)
});
});
There are two possible mistakes:
1.check the connection between client and server. as mentioned above.
2.check the table name, data type of attributes, name of attributes you are providing.
The rest endpoint is / and you are calling products change your backend code as below.
router.post('/products', (req, res) => {
const { c_id, p_name, p_price } = req.body
const q =
`
INSERT INTO products (c_id,p_name,p_price)
VALUES("${c_id}", "${p_name}" , "${p_price}")
`;
con.query(q, (err, result, fields) => {
if (err) throw err;
res.json(result)
});
});

Passing a variable from ReactJS frontend to NodeJS back end using a GET route

I am working on a react app and am trying to find a way to pass a variable I define in my front-end (Question.js) to my back-end (server.js) so that I can issue different queries. I have the code
//Question.js
state = {
data: null
};
componentDidMount() {
this.callBackendAPI()
.then(res => this.setState({ data: res.express }))
.catch(err => console.log(err));
}
callBackendAPI = async () => {
const response = await fetch('/express_backend');
const body = await response.json();
if (response.status !== 200) {
throw Error(body.message)
}
return body;
};
//server.js
con.connect(function (err) {
if (err) throw err;
con.query("SELECT question FROM s1questions WHERE ID = 1", function (err, result, fields) {
if (err) throw err;
app.get('/express_backend', (req, res) => {
var x = JSON.stringify(result[0].question);
res.send({ express: `${x}` });
});
});
});
Your sever should probably split your database connection from your route handler definitions. Also, you could use query parameters to access questions based on their id in the database.
// question.js
callBackendAPI = async () => {
const response = await fetch(`/express_backend?questionId=1`);
const body = await response.json();
if (response.status !== 200) {
throw Error(body.message)
}
return body;
};
// server.js
app.get('/express_backend', (req, res) => {
const { questionId } = req.query;
// query database for question by id
});

Fetch API response with react and Express.js won't show any result with console.log

I have a login form that sends data to an Express.js backend using fetch. On the client side, when I want to display the results of the fetch call when it completes nothing is displayed (and it never reaches the data callback). I don't seem to be getting any errors, but I know that the data is successfully being sent to the backend.
Here's the Express.js server code:
const express = require('express');
const User = express.Router();
const bcrypt = require('bcrypt');
const user = require('../Models/user');
this is edited
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
User.route('/').get(getRouteHandler);
User.route('/register').post(postRouteHandler);
User.route('/login').post(loginRouteHandler);
module.exports = User;
And here's the fetch call:
fetch('http://localhost:4000/login',{
method: 'POST',
headers: {
'Accept': 'application/json,text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({
userName: this.state.userName,
password: this.state.password,
}),
}).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});
In your loginRouteHandler, if the bcrypt compare succeeds nothing is returned in the response. So in the first branch of the if statement, put res.send('Success!') or something similar.
Here's an example:
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
UPDATE: you're also not getting the output of the fetch response with .text() or .json(). You have to update the fetch call to the following:
fetch(/* stuff */).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
return response.text()
}).then((data)=>{
console.log(data)
});
Remove ok from response.ok
Remove .then((data)=>{ console.log(data) });
And check console log.
}).then((response)=>{
if(response){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});

Categories

Resources