ReactJS making a http request and displaying the result on page - javascript

I have a search bar with a button. when the button is clicked, the search_on_click function runs. This function is supposed to retrieve the html of the URL and display it on the page.
class App extends Component{
constructor(props){
super(props)
this.state = {
html: []
}
this.search = this.search.bind(this)
}
search(){
const URL = 'https://www.zerochan.net/Re%3AZero+Kara+Hajimeru+Isekai+Seikatsu?s=fav'
axios.get(URL)
.then(data =>{
console.log(data)
this.setState({
query: data
})
})
.catch(function(error){
console.log(error);
})
}
render(){
return(
<div>
<button onClick={() => this.search()}>search</button>
<div>{this.state.query}</div>
</div>
This is the code i have so far. The problems/questions are:
axios does not console.log the html or even seem to run
i have tried fetch/requests and the problems are more or less the same
is there a better way to do this?
i do not think the is a CORS problem because i have used CORS allowing chrome extension.
.catch() does not log anything to console either
thank you for your time.

The URL you are trying to get isn't a valid resource. You should hit a URL that returns some data, in your case its an HTML which has no API for transferring data or CORS enabled for you to access it. Therefore, you won't get the expected result and axios won't be able to deliver your request.
Example of a valid API request https://codesandbox.io/s/jv73ynwz05
componentDidMount() is invoked immediately after a component is
mounted (inserted into the tree). Initialization that requires DOM
nodes should go here. If you need to load data from a remote endpoint,
this is a good place to instantiate the network request.
componentDidMount() {
// Note the api in the URL path, which means it is a valid endpoint
axios.get('https://randomuser.me/api/?results=50')
.then(response => {
const data = response.data.results;
this.setState({ data })
})
.catch(error => {
console.log(error);
})
}
See a similar issue here: Enable CORS in fetch api

Related

Why am I getting generic "TypeError: Failed to fetch" errors?

When fetching from some APIs, I get TypeError: Failed to fetch errors.
For example, the URL used in the snippet below is an example provided by an API provider. It can be accessed without a key. It works fine in my browser but will throw an error in my code.
Fetching from another public API, https://api.punkapi.com/v2/beers/random, works perfectly.
What is the difference between these APIs that prevents me fetching from some and works for others others?
export default function App() {
useEffect(() => {
fetch(
'https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=439d4b804bc8187953eb36d2a8c26a02'
)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
console.error(error);
});
}, []);
return null;
}
you can't get data from samples
caused API is blocked due to CORS header ‘Access-Control-Allow-Origin’ missing
you need to generate api key(https://openweathermap.org/price) and connect to api
//ex:
api.openweathermap.org/data/2.5/weather?appid={your api key}&....

Axios not retuning correct data

I have a React application, where I am fetching some data, from an endpoint, where I am expecting two different arrays as response.
When i go into the terminal, i see that, it says Array(2), but when i open up the data tab it only displays one array.
This anybody know if this is a bug or if this is something wrong with my application.
I tried from two separate clients (postman and regular browser), where there was no issue at all, so I am a bit confused, to as why this is happening?
I have taken into account, that the requests are async.
Here is my full code.
const [{data, loading, error}, refetch] = useAxios(fetchInvoiceData);
useEffect(() =>{
if(!loading){
const ids = data.encodedImage.map(entry => entry._id)
console.log(ids)
console.log(fetchMultipleLabelData(ids))
setLoadingPages(true)
axios.get(fetchMultipleLabelData(ids)).then(res =>{
console.log(res)
setLoadingPages(false)
const categories = generateCategories(res.data);
const initialState = generateInitialState(res.data);
setCategories(categories)
console.log(categories)
setGlobalState(initialState)
}).catch(err =>{
console.error(err)
})
}
}, [loading])
I have tried making it conditional by using a loading state to 'wait' with doing the http request.
Furthermore, since it gives a response, i assume, that it would return the full data???
EDIT:
i have no tried Stringifying the json, and logging out the regular output aswell with the following result
console.log(JSON.stringify(res.data))
console.log(res.data)

ReactJS: how to make two backend requests at once?

Is it possible to make two backend requests at once from react?
The code below is the first backend call. The post request gets send to the backend and then I would like to do another request. Is it possible at all? Or do I have to wait for the backend response until the next request could be made?
What I basically want is to get information about how many files have been uploaded. The upload could take 3 minutes and the user right now only sees a loading icon. I want to additionally add a text like "50 of 800 Literatures uploaded" and 10 seconds later "100 of 800 litereratures uploaded".
This is basically my code :
class ProjectLiterature extends Component {
constructor(props) {
super(props);
this.state = {
isLoading:"false",
}
}
addLiterature(data, project_name) {
this.setState({ isLoading:true }, () => {
axios.post("http://127.0.0.1:5000/sendLiterature", data })
.then(res => {
this.setState({ isLoading: false })
})
})
}
If both requests do not depend on each other, you can make use of JavaScript's Promise.all() for the above purpose.
const request1 = axios.get('http://127.0.0.1:5000/sendLiterature');
const request2 = axios.get(url2);
Promise.all([request1,request2]).then([res1, res2] => {
// handle the rest
}).catch((error) => {
console.error(error);
// carry out error handling
});
If the second request relies on the response of the first request, you will have to wait for the first request to be completed as both requests have to be carried out in sequence.
const res = await axios.get('http://127.0.0.1:5000/sendLiterature');
// carry out the rest
You can see axios docs for this purpose, they support multiple requests out of box.
You can use Promise.all instead of axios.all as well but if one of requests fails then you won't be able to get response of successful calls. If you want get successful response even though some calls fails then you can use Promise.allSettled.

Redirect/ Routing issues in React and Express

I am creating a flight search app that makes external api calls. The data will be reorganized and returned in search results component.
On submit, the data is sent to express and takes about 10 seconds or more to complete all the api calls.
I think I need a loader at some point for during the delay of api calls, but also I am unsure of how to send/render the data.
As it stands, I have two pages home.js- '/' where i make the search and is sent to the server side, and prices.js- '/search' which when loaded fetches the data from the json file. but i do not have them connected
Both files work but I need to connect them. When I press submit, the user inputs are sent to server and the api calls are made but in order to see the results i have to manually refresh localhost:3000/search.
In express app after all the api calls, I tried res.redirect method, however the error given was setting the headers after sent to the client.
In react, I tried after submitting, to redirect to the search page. However I could not get it to redirect and also as soon as the /search page is called, it fetches the data from the file. This will happen before the api has finished writing to file and therefore the previous search results will render.
--in app.js
setTimeout(() => {
Promise.all([promise, promise2]).then(values => {
return res.redirect('http://localhost:3000/search');
});
}, 25000);
I had to wrap the api calls in promises so it will only redirect after all is written to file.
(in react prices.js)
componentDidMount() {
fetch('/search')
.then(res => {
return res.json()
})
.then(res => {
console.log(res.toString());
this.setState({flightData: res});
})
.catch(error => console.log(error));
}
home.js
home.js
```
onChange = (e) => {
this.setState({
originOne: e.target.value, originTwo: e.target.value});
};
onSubmit = (e) => {
e.preventDefault();
const { originOne, originTwo ,redirectToResult} = this.state;
};
```
app.js - I have all the functions calling each other in a waterfall style ( probably not the best way I know)
app.post('/', function getOrigins(req,res) {
var OrigOne;
var OrigTwo;
....
function IataCodeSearchOrg1(res, OrigOne, OrigTwo) {
...
findPrices(res,A,B)
}
function findPrices(res, A, B) {
promise = new Promise(function (resolve) {
...
}
}
All the methods are called within eachother. The api calls are in a loop and after each iteration they are written to the json file.
All these functions are in the app.post method and i tried to res.redirect but it did not work.
EDIT:
You can't redirect server-side from an XHR request. You would need to redirect client-side.
e.g.
componentDidMount() {
fetch('/search')
.then(res => res.json())
...
.then(() => window.location = '/myredirecturl')
}

Can't set Cookies in browser even though header is present

I was working on adding cookies to my project, full source here, but I ran into an issue where I can't set the cookies properly. I made a new api route that just creates a cookie and sends an object to the client.
server/routes/todo.routes.js
router.get('/todos', (req, res) => {
res.cookie('mycookie', 'a_value')
return res.send([{id:'1',isCompleted:false,text:'something'}])
})
If I call this api route directly, the browser renders the object and the cookie is set. The problem is when I call this api via AJAX from a rendered page, I still get the same response, but cookies aren't set. NOTE: I export the router and do app.use('/api', exported_object_here), so the URL is /api/todos.
shared/actions/todo.actions.js
export const getTodos = () => {
return (dispatch) => {
return fetch('/api/todos')
.then(response => response.json())
.then(todo => dispatch(_receiveTodos(todo)))
.catch(err => dispatch(_errorHandler(err)));
}
};
I have no idea why the browser would act differently in that situation, especially with something so simple. Do you all have any clue what could cause this?
You need to set withCredentials on your XHR request (https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)

Categories

Resources