Codesandbox.io sending back html data instead of Json data - json

I'm currently working on a code problem on codesandbox where I am trying to use a http get request to retrieve json data from the link provided. However, when I console.log the response, I'm only receiving html data, which I have never seen before when making an http request. Has anyone else run into this issue with displaying JSON data and have tips for using codesandbox?
Thank you!
import React, { useState } from "react";
import "../styles.css";
import axios from "axios";
export default function App() {
axios
.get(`www.sbir.gov/api/solicitations.json?keyword=sbir`)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}

Instead of console.log(response)
Try
console.log(response.json())

I'm not sure why this is the case, but you need to use https.
In your case you should be using https://www.sbir.gov/api/solicitations.json?keyword=sbir instead of www.sbir.gov/api/solicitations.json?keyword=sbir.
I found an example codesandbox here, when you remove https://, console logging the response outputs a html script.

Related

How to use fetch() in react front-end to get data from express back-end?

I'm trying to make a full-stack web-app using react and express. It's going pretty well atm but here's my problem:
So I have express running in back-end. All paths are used by react router except for '/api'. At the '/api/blogposts' path my server.js send the results of a query I made to the mySQL server. (I've checked it and this part works. If I browse to /api/blogposts my browser shows a json with the contents of my blogposts table).
My problem is with getting it to show in my react front-end. I'm trying to use fetch() but it doesn't work. Here's my code for the component that is supposed to fetch the blogposts:
import React from 'react';
import './Blogposts.css';
import SingleBpost from '../SingleBpost/SingleBpost.js';
class Blogposts extends React.Component {
constructor(props) {
super(props);
this.state = {
receivedPosts: []
};
}
async getBpostsFromServer() {
const response = await fetch("/api/blogposts");
let myPosts = await response.json();
this.setState({receivedPosts: myPosts});
}
componentDidMount() {
this.getBpostsFromServer();
}
render() {
console.log(this.state.receivedPosts);
return(
<div id="Blogposts">
<SingleBpost title="OwO" date="18/12/2021" author="Kepos Team" body="Hello, this is a test for the blogposts!" />
</div>
);
}
}
export default Blogposts;
Just to clarify the {this.state.generateBlogpost()} in the render method is just to check if I can get the data for now. Once this works I will feed it into another component's props like this:
<SingleBpost title={this.state.generateBlogpost().title} date={this.state.generateBlogpost().date} author={this.state.generateBlogpost().author} body={this.state.generateBlogpost().body} />
Anyways: does anyone know why this doesn't work? I've tried a few things but I just can't get it to work. What am I doing wrong?
Thanks in advance for any help!
You need to set the state of the variable receivedPosts in the fetch function like this :
this.setState({receivedPosts: results});
Also, you can call the function generateBlogpost() at the load of the Component Blogposts by adding the following function :
componentDidMount() {
this.generateBlogpost();
}
this one is useless
.then((results) => {
this.state.receivedPosts = results;
});
return this.state.receivedPosts;
}
//instead you should use setState({receivedPosts: data.data})

Why is my API requset returning only a string payload [JavaScript]

I am new to working with API and I am working on a web-extension to fetch a random quote.
Each time I refresh the page the output works fine with response.data however, I would like to use each object from the responses... and not have the entire data on the page so I can add my custom styles.
I am using Axios + pure js
and I would like to access these values
Can someone please tell me, what I am doing wrong here?
For now, all I can access is request.data
axios
.get(url)
.then(function (response) {
showTextToUser(response.data);
//NOT WORKING console.log(response['verse']);
})
.catch(function (error) {
console.log(error);
});
Here's my request using axios
This is how axios response object look like
{
config:{},
data:{ --PAYLOAD YOU SENT FROM SERVER --},
headers:{},
request:{},
status: // status code,
statusText:''
}
I think you will find the verse object in data object as response.data.verse

How to make my react app dynamic when fetching api?

In my react app, im using Im using MySql and NodeJS. When im fetching api, the code looks something like this
axios.post('http://localhost:5000/api/product-from-search', obj)
.then(function (response) {
state.setState({ searchInputResult: response.data })
})
.catch(function (error) {
console.log(error);
})
}
how can i make it dynamic so that i only need to write
axios.post('/api/product-from-search', obj)
You can define your baseURL outside your component and use template literals in your function call.
const baseURL = "http://localhost:5000"
~~~
axios.post(`${baseURL}/api/product-from-search`, obj)
excuse me if I'm not understanding your question correctly.
I think you are asking how to set your baseURL for Axios, so you can type all your routes as relative instead of absolute ('/api/...' instead of 'http://address:port/api/...')?
You should not need to write the http://localhost:5000 part of the path. Axios should work fine with just just the relative '/api/...'.
If that's NOT the case, I think you might have a CORS issue. (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
If you've used create-react-app, then in the package.json (of your react app) add the following line just before the closing curly brace:
"proxy": "http://localhost:5000"
EDIT: Don't forget to restart your server after doing this!
If it's a CORS problem, the request is failing because your server is at a different origin (in this case, different port) than your front end, which the browser will block for security reasons.
Of course, you can use AXIOS configuration to set a baseURL so that you don't have to include it in every route as described here: (https://github.com/axios/axios)
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
But I don't think that's your actual issue. Try the proxy in your package.json first.
Cheers!
You can create a separate 'helper.js' file where you can define a function to configure axios post request as per the requirements.
import React from 'react';
let baseUrl = "http://localhost:5000";
export function post(apiEndpoint, payload){
return axios.post(baseUrl+apiEndpoint, payload,
options = { headers: {
'Authorization': 'Your token goes here',
}})
.then((response)=>{
return response;
}).catch((err)=>{
console.log(err);
})
}
Now, call this named export into your file with required params.

React Unable to Access Json Resposne from API

In my website on login,i get a confirmation and a token which i need to store and pass as a property throughout all the pages.I am able to receive the token,but i am unable to store the value for the token and store it as a state value.
Here is the code i have tried so far.
import React from 'react'
import ReactDOM from 'react-dom'
import {Login_Submit_style,Login_button_style,Login_text_field_style,
password_style,para_login_style} from './style'
import Supers from 'superagent'
class Login extends React.Component
{
constructor(props)
{
super(props);
this.state={username:'',password:''}
this.Login_data_password=this.Login_data_password.bind(this)
this.Login_data_username=this.Login_data_username.bind(this)
this.MainRedirect=this.MainRedirect.bind(this)
this.api_call_login=this.api_call_login.bind(this)
}
Login_data_username(e)
{
this.setState({username:e.target.value})
}
Login_data_password(password)
{
this.setState({password:password.target.value})
}
MainRedirect()
{
window.location = '/main';
}
api_call_login()
{
Supers.post('http://127.0.0.1:8000/user_ops/user_login/')
.send({'username':this.state.username,'password':this.state.password})
.then(response => response.json())
.then(responseData=>{
console.log(responseData);
})
}
render()
{
return(
<div style={{background:'yellow'}}>
<div>
<h1 style={{marginLeft:550}}>Login Page</h1>
<div>
<p style={para_login_style}><b>Username</b></p>
<input type="text" style={Login_text_field_style} onChange={this.Login_data_username}/>
<h2>{this.state.username}</h2>
</div>
<div>
<p style={para_login_style} ><b>Password</b></p>
<input type="password" style={password_style} onChange={this.Login_data_password}/>
</div>
<div>
<button style = {Login_Submit_style} onClick={this.api_call_login}> Log in </button>
</div>
</div>
</div>
)
}
}
This is the Format in which i get the response:
{"Successful_Login": "True", "token": "d278f30445aa0c37f274389551b4faafee50c1f2"}
So ideally i would like to store the values for both the keys returned from the json output.Adn when i use response.body,i am able to get the data in the above format.
I don't know if this will be helpful to you, but I'll try.
Things like XHR calls from a browser to an API are done asynchronously. What you get back is a promise that will execute a function you give it when the call to the API is completed. Your code rightly has a callback function.
However, I don't think that callback function can call setState, because I think (I might be wrong) React wouldn't like it.
I use Redux for React as a way of storing stuff that the rest of the app can just grab when it needs it. Better still, Redux is integrated into React in such a way that whenever this central database is updated, any component that pulls in a piece of data from it (via props) gets updated (re-rendered) automatically.
I think I should point you to the documentation for Redux for more information. There are alternatives to Redux, too.
Good luck, and ask more questions if you get stuck.
In order to set a new state with the values from a json response, I ideally call this.setState right in your promise response.
api_call_login()
{
Supers.post('http://127.0.0.1:8000/user_ops/user_login/')
.send({'username':this.state.username,'password':this.state.password})
.then(response => response.json())
.then(responseData=>{
this.setState({
Successful_Login: responseData.Successful_Login,
token: responseData.token
})
}
state will be updated when response arrives.
If possible try to use lowercase or camelCase to your keys.
It would be great if you could post link where we can see what exactly is going on, but the way I understand this you would have to add .set('Accept', 'application/json') in your request to get correct json. So, your code should be like:
Supers.post('http://127.0.0.1:8000/user_ops/user_login/')
.send({'username':this.state.username,'password':this.state.password})
.set('Accept', 'application/json')
.then(response => response.json())
.then(responseData=>{
console.log(responseData);
})
Since I cannot test, you would have to look if it works. Alternatively, I would suggest you to try using superagent
Let me know if it helps!

Accessing state in React render method after API request

I'm working on my first complicated React app and I am making a request to a movie API. My site allows the user to do a search in a searchbar for whatever movie, show, actor, etc... that they are searching for. I'm pulling the user's search query and inserting it into an api request like this:
export const getDetails = (id) => {
return new Promise(function(resolve, reject) {
axios.get(`https://api.themoviedb.org/3/movie/` + id +`?api_key=&language=en-US`)
.then(function(response) {
resolve(response)
})
.catch(function(error) {
reject(error)
})
})
}
I'm able to get the data like this and console.log it:
import React, { Component } from 'react';
import Header from '../header';
import {Link} from 'react-router-dom';
import axios from 'axios';
import Footer from '../Footer.js';
import Searchbar from '../header/searchbar.js';
import List from '../results/list';
import {getDetails} from '../api/getDetails';
class Detail extends Component {
constructor(props) {
super(props);
this.state = {
id: this.props.match.params.id,
result: null,
error: false,
}
}
componentWillMount() {
getDetails(this.state.id).then(function(response){
this.setState({result: response});
console.log(response.data.original_title);
console.log(response.data.homepage);
console.log(response.data.popularity);
console.log(response.data.release_data);
console.log(response.data.overview);
}.bind(this)).catch(function(err) {
this.setState({
result:"There was a problem loading the results. Please try again.",
error: true
})
}.bind(this))
}
render() {
return(
<div>
<Header/>
<div className="details-container">
<h2>Details: </h2>
</div>
</div>
)
}
}
export default Detail
Console.logging it in the componentWillMount function successfully logs the data but I am not able to access the data in the render function via something like {response.data.orginal_title). How would I render the data being logged in componentWillMount?
TLDR; You can access your state variables from within your render function via this.state. Something like: console.log(this.state.result.data.origin_title) outside of the jsx and {this.state.response.data.orginal_title} inside the jsx.
P.S. You are using the correct this.
The following are picky recommendations and explanations, feel free to disregard.
It's recommended to make requests for data in componentDidMount. That can be read here in the docs for componentDidMount.
You're using arrow functions already in your get details function, if you convert the rest of your functions to arrow functions you no longer have to explicitly bind this to each one; it's automatically set be the this of it's parent. See the "No Separate This" section in the MDN docs
If you don't need any of the header information I would save response.data into your state so you don't have to type as much when you want to access the data. this.state.result.original_title vs this.state.result.data.original_title. That's just me and I'm lazy.
axios does return a promise like Eric said so you don't actually need to wrap it in the extra promise. You can just straight up return it and since arrow functions automatically return one line expressions you can spiff that up into a one liner:
export const getDetails = id => axios.get(`https://api.themoviedb.org/3/movie/${id}?api_key=&language=en-US`)
Finally you should be able to access the data you've stored in your state from your render function as mentioned in #3 above. Outside of the JSX you can console.log it like normal console.log(this.state.result), inside your JSX, however, you will need to make sure you escape with {} like: <div>{this.result.original_title}</div>
Small working example here: https://codesandbox.io/s/zqz6vpmrw3
You can simply use
{this.state.result}
inside the render.