React/Redux + super agent, first call gets terminated
Asked Answered
T

3

6

I am writing a react-redux app where I am making some service calls in my middlewares using superagent. I have found a very strange behavior where the first call to my search api always gets terminated. I have tried waiting 10-30 seconds before making the first call, and logging every step along the process and I cannot seem to pinpoint why this is happening.

My action creator looks like

export function getSearchResults(searchQuery) {
return {
        query: searchQuery,
        type: actions.GO_TO_SEARCH_RESULTS
    }
}

It hits the middleware logic here :

var defaultURL = '/myServer/mySearch';

callPendingAction();

superagent.get(defaultURL)
        .query({query: action.query})
        .end(requestDone);


//sets state pending so we can use loading spinner
function callPendingAction() {
    action.middlewares.searchIRC.readyState = READY_STATES.PENDING;
    next(action);
}

//return error or response accordingly
function requestDone(err, response) {
    console.log("call error", err);
    const search = action.search;
    if (err) {
        search.readyState = READY_STATES.FAILURE;
        if (response) {
            search.error = response.err;
        } else if (err.message) {
            search.error = err.message;
        } else {
            search.error = err;
        }
    } else {
        search.readyState = READY_STATES.SUCCESS;
        search.results = fromJS(response.body);
    }
    return next(action);
}

The query is correct even when the call is terminated, I get this err message back :

Request has been terminated
Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.
at Request.crossDomainError (http://localhost:8000/bundle.js:28339:14)
at XMLHttpRequest.xhr.onreadystatechange (http://localhost:8000/bundle.js:28409:20)

It appears the page refreshes each time too.

I cannot seem to find any clues as to why this happens, it seems not matter what the first call fails, but then it is fine after that first terminated call. Would appreciate any input, thanks!

UPDATE: so it seems this is related to chrome, I am on Version 47.0.2526.80 (64-bit). This app is an iframe within another app and I believe that is causing a problem with chrome because when I try this in firefox there is no issue. What is strange is only the first call gives the CORS issue, then it seems to be corrected after that. If anyone has input or a workaround, I would greatly appreciate it. Thanks for reading.

Turcotte answered 23/12, 2015 at 15:9 Comment(1)
I have the same problem currently. Using Chrome 50.0.2661.86. Neither Firefox 45.0.2 or Firefox 46.0 had the issue. Safari works as well. I'm not using redux yet so I don't think it's related to that. For the API server I'm using Koa with the npm module kcors for CORS. withCredentials doesn't appear to work, but that's because CORS stops working all together when I add withCredentials.Tailorbird
T
9

Had the same problem, just figured it out thanks to the answer provided by @KietIG on the topic ReactJS with React Router - strange routing behaviour on Chrome.

The answer had nothing to do with CORS. The request was cancelled because Chrome had navigated away from the page in the middle of the request. This was happening because event.preventDefault() had not been called in one of the form submit handlers. It seems Chrome handles this differently than other browsers.

See the answer link above for more detail.

Tailorbird answered 28/4, 2016 at 0:58 Comment(2)
Had the same issue, but I don't use react or redux. Also, I don't have a form element, I just use superagent. So where should I insert preventDefault?Nickienicklaus
At the beginning of the whatever handler method is called upon the action.Tailorbird
W
1

In my case this was happening when I tried to set a random HTTP request header (like X-Test) on the client side and either AWS Lambda rejected it during the OPTIONS request or something else did that.

Wellturned answered 11/4, 2017 at 18:13 Comment(0)
G
0

I don't know about the side effects, but you're getting CORS errors. Add the .withCredentials() method to your request.

From the superagent docs:

The .withCredentials() method enables the ability to send cookies from the origin, however only when "Access-Control-Allow-Origin" is not a wildcard ("*"), and "Access-Control-Allow-Credentials" is "true".

This should fix it:

superagent.get(defaultURL)
        .query({query: action.query})
        .withCredentials()
        .end(requestDone);

More information on Cross Origin Resource Sharing can be found here.

Glove answered 23/12, 2015 at 15:39 Comment(3)
I was thinking this was the right idea, but it doesn't seem to work. I think it might be a bug with chrome right now because of this setup. Thanks for all the info!Turcotte
I'm having the same problem. When I add withCredentails() CORS stops working altogether. Not sure if the original issue would be resolved if I can fix whatever is happening when withCredentails() is added.Tailorbird
After further testing the withCredentials() option did not solve the issue (withCredentials was made to work once the Access-Control-Allow-Credentials header was added, but the problem described in the question remained).Tailorbird

© 2022 - 2024 — McMap. All rights reserved.