How do I get data from Express endpoint in a React component? - javascript

I have a simple react component and express endpoint that returns the string "sample data". I'm just trying to hit that endpoint in my react app and store the text in state and display it on the screen.
My component:
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: null
};
}
componentDidMount() {
this.callBackendAPI()
.then(res => this.setState({ data: res.data }))
.catch(err => console.log(err));
}
async callBackendAPI() {
const response = await fetch('/sampleData');
const body = await response.json();
if(response.status !== 200) {
throw Error(body.message)
}
return body;
}
render() {
let data = this.state.data || 'there is no data';
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">{data}</p>
</div>
);
}
}
export default (App);
The backend endpoint:
app.get('/sampleData', function(req, res) {
res.send('sample data');
});
I'm not sure I need response.json() since the endpoint just returns plain text, I actually get an error with this code SyntaxError: Unexpected token s in JSON at position 0. When I just use response nothing happens and the text just shows up as "there is no data" since the state is empty.
How can I get the text from my endpoint into the components state and displayed on screen?
Thanks!

response is a Response object. fetch will give you access to it when the HTTP response header has been read, not the response body - this is why you have to await on response.json(), as you can't parse the body data until it has finished transferring.
This same principle applies when reading plain text from a Response - you need to await on response.text(), to allow the response to finish being read. In this case, you'll also need to amend your setState and Error , as body will just be a string, not an object.
This might all seem a bit unintuitive, but it's for good reason - because you get a Response as soon as the response starts being transferred, you can take actions based on the status/HTTP headers while the rest of the response is still loading.

My guess is that your endpoint does not have the res.data in the response.
I would recommend throwing a console.log(res) in your .then() to see what is returned - if nothing is returned, I would double check you are returning on the url provided.
Your code looks fine, I tested it quick and it looks good to me, it was just a matter of getting the response data correctly.

I think your error is here:
app.get('/sampleData', function(req, res) {
res.send('sample data');
});
you send a text not a Json so when you try to receive data with
const body = await response.json();
you have that error.
so you can change your back-end and send Json object as
app.get('/sampleData', function(req, res) {
res.send({text:'sample data'});
});
or as Joe Clay had suggest you, you can receive text with
const body = await response.text();

Related

NEXTJS - fetching data from the server

I want to fetch data from the nextjs server on the front end, however the code after fetch() doesn't work in the onSubmit() function.
here is the /test page
pages/test
const onSubmit = (data) => {
console.log("________");
users.map(async (user, index) => {
if (data.email === user.email) {
if (data.password === user.password) {
console.log("hi");
const data = await fetch("http://localhost:3000/api/test");
// after the fetch, this code does not run
console.log("back-end is: ", data);
}
}
});
};
and here is my code in /api/test
export default async function student_method(req, res) {
return console.log("get in server");
}
so please what is the problem??
i'm try to get the data inside the database
so we need to use fetch() method but fetch() work succesfully but code after fetch() does not work
I think the issue is using the return statement on the server side. NextJS provides helper methods in the res object you receive in your server-side function.
Try something like this:
res.status(200).send("get in server");
For details, see here: API Routes: Response Helpers
const data = await fetch("http://localhost:3000/api/test");
The problem is that line. There you waiting a Promise resolve, but if you see you api/test you only return a log.
Please try returning a Promise.
The code is not working now because you're waiting for the server response but you aren't sending anything from the server.
You should send response to the client like this:
export default async function student_method(req, res) {
/* status code 200 or any other status codes */
res.status(200).send("get in server");
}

Response returning undefined react js axios

I trying to view status of a variable (salesforecasting) in database. Its responds by sending true or false which is received fine in Postman. However when it gets to react, it is shows undefined on console. if i see whole response object, there i can see value has return correctly but when i try to print it, it shows undefined.
in routes/api/salesforecasting.js
router.post('/view', function(req, res) {
const email="Hamzakhan003#gmail.com"
Customer.findOne({Email:email})
.then(data=>{
if(data){
let salevalue=data.Salesforecasting
res.send({
value: salevalue
});
}
});
});
in react file
componentDidMount(){
return axios.post('http://localhost:3000/api/sales-forecasting/view')
.then(response => {
//const output = response.value
const value = response.value;
{console.log(arr.value)}
this.setState({
added: value
});
});
}
I think u need to check in response.data.value instead of response.value.
axios populates the entire server response in response.data

Append a query param to a GET request?

I'm trying to make a simple API that calls another API that will return some information. The thing is, in order to connect to the second API, I need to attach query parameters to it.
So what I've tried to do so far is to use an axios.get in order to fetch the API. If I didn't need to add queries on top of that, then this would be really simple but I'm having a really hard time trying to figure out how to attach queries on top of my request.
I've created an object that pulled the original query from my end and then I used JSON.stringify in order to turn the object I made into a JSON. Then, from my understanding of Axios, you can attach params my separating the URL with a comma.
On line 6, I wasn't sure if variables would carry over but I definitely can't have the tag var turned into the string "tag", so that's why I left it with the curly brackets and the back ticks. If that's wrong, then please correct me as to how to do it properly.
the var tag is the name of the query that I extracted from my end. That tag is what needs to be transferred over to the Axios GET request.
app.get('/api/posts', async (req, res) => {
try {
const url = 'https://myurl.com/blah/blah';
let tag = req.query.tag;
objParam = {
tag: `${tag}`
};
jsonParam = JSON.stringify(objParam);
let response = await axios.get(url, jsonParam);
res.json(response);
} catch (err) {
res.send(err);
}
});
response is SUPPOSED to equal a JSON file that I'm making the request to.
What I'm actually getting is a Error 400, which makes me think that somehow, the URL that Axios is getting along with the params aren't lining up. (Is there a way to check where the Axios request is going to? If I could see what the actual url that axios is firing off too, then it could help me fix my problem)
Ideally, this is the flow that I want to achieve. Something is wrong with it but I'm not quite sure where the error is.
-> I make a request to MY api, using the query "science" for example
-> Through my API, Axios makes a GET request to:
https://myurl.com/blah/blah?tag=science
-> I get a response with the JSON from the GET request
-> my API displays the JSON file
After looking at Axios' README, it looks like the second argument needs the key params. You can try:
app.get('/api/posts', async (req, res, next) => {
try {
const url = 'https://myurl.com/blah/blah';
const options = {
params: { tag: req.query.tag }
};
const response = await axios.get(url, options);
res.json(response.data);
} catch (err) {
// Be sure to call next() if you aren't handling the error.
next(err);
}
});
If the above method does not work, you can look into query-string.
const querystring = require('query-string');
app.get('/api/posts', async (req, res, next) => {
try {
const url = 'https://myurl.com/blah/blah?' +
querystring.stringify({ tag: req.params.tag });
const response = await axios.get(url);
res.json(response.data);
} catch (err) {
next(err);
}
});
Responding to your comment, yes, you can combine multiple Axios responses. For example, if I am expecting an object literal to be my response.data, I can do:
const response1 = await axios.get(url1)
const response2 = await axios.get(url2)
const response3 = await axios.get(url3)
const combined = [
{ ...response1.data },
{ ...response2.data },
{ ...response3.data }
]

Get request yields response with data in it, but when accessing .data specifically it yields undefined

Apologies if the terminology is not great, still new to fullstack.
Hello! I am trying to get all the users in my DB. The get() response is OK as the client is receiving the response (see image below)
The problem is that when I try to fetch the .data I get undefined.
Here's my Vue Component
import UserService from '#/services/UsersService.js'
export default {
data () {
return {
users: null
}
},
async mounted () {
// GET request for all users.
this.users = UserService.index().data
console.log('The response is OK', await UserService.index())
console.log('when trying to fetch the .data I am getting ', await this.users)
}
}
The index() function
import Api from '#/services/Api'
export default {
index () {
return Api().get('users')
}
}
Everything works fine, except that I get undefined data...
I think you forgot to fetch the data asynchronously?
async mounted () {
// GET request for all users.
- this.users = UserService.index().data
+ const res = await UserService.index()
+ this.users = res.data
console.log('The response is OK', await UserService.index())
console.log('when trying to fetch the .data I am getting ', await this.users)
}
You correctly use await syntax in the first console.log, which might explain why the data return correctly.

ReactJS get token string from API fetch

I set up an API in Java. But now I'm developping a client in ReactJS. The authentication uses a JWT Token. With Postman, when I send a POST request to the authentication URL, it returns me a JWT token like this :
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZHVzZXIiOjEsImlzcyI6ImF1dGgwIn0.0BXAQl-yMIDeAU6Emppo6LBIm1RAdLa9vDWbQkdLs1o
That's exactly what I want. But I don't know how to retrieve a string after a fetch call in ReactJS.
I tried to use the promises and wrote this :
.then((data) => {
data.text().then((token) => {
alert(token)
})
})
But it returns me nothing, I have an alert with no text.
How to get String from the Object Response returned by the fetch ?
Maybe you back end server return Content-Type=application/json? Instead text() method try using json().
Try this:
fetch('/next/page')
.then(function(response) {
return response.text();
})
.then(function(text) {
// <!DOCTYPE ....
console.log(text);
});
I was facing the same issue and was able to get the token with this:
.then(res => res.json()).then(res => {
let token = res.token;
console.log("token: ", token);
});
Source:
https://developer.mozilla.org/en-US/docs/Web/API/Body
The text() method on that response object is what you are looking for.
Using await syntax I think is a bit simpler than using then() With await, this in this.setState() is scoped as expected.
async getStrResponse() {
const response = await fetch('myController/GetStringTest');
const stringResponse = await response.text();
this.setState({ someStr: stringResponse, loading: false });
}

Categories

Resources