React onClick event calls API twice - reactjs

I have a simple React component, a button and a function which calls an API endpoint. When I click the button the API inside event gets called twice. I have read many posts here on stackoverflow and tried all of them but still have same issues.
Moreover, even though I can see 2 records in db for each call, in the Google Dev tools shows only 1 xhr call which is wired.
I have already tried to pass function reference instead of function itself and even called function via () => { } but same result.
<button type="button" onClick={ this.onSubmitForm }>Save</button>
onSubmitForm = (e) => {
// e.preventDefault();
const response = axios.post('http://localhost/util/index.php/api/record', {name: 'test'} );
console.log(response) // Even this line is logged once in console ;
}

Neither your react app nor the API, it is the browser itself. Have a look at this https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
A preflight request to let the server know what HTTP method will be used when the actual request is made.

If in the Google Dev tools shows only 1 xhr call. Then it's not a front-end problem. It might be something wrong with the api function in server side. Maybe it calls the insert query twice.

Related

Fetch data from API and pass the fetched data as parameter to other API to fetch regarding data?

I am working on an app and getting all the data from API's for different components.And when calling login api I am getting the json as response with user details. I have a component which requires some of the user details to pass to another API to fetch regarding data. Currently I am fetching data of the components by passing actual user details as a parameter to the API, and I want to make it dynamic.
Where Whenever a user will logged in, other API's should dynamically take the required parameters and fetch the json data. How can I achieve this?
Create an async function that logs the user in and on the result, call the second API conditionally with the result of the login call.
async function loginUser (params){
try {
// api call here
// if everything is successful
return {
success:true,
data: userObject
}
} catch(e){
return{
success:false,
error:e
}
}
}
const result = loginUser(params)
if(result.success){
// perform another call whcich requires userObject
}

Refreshing list After Deleting data Data is not refresh in mui-datatables

I simply delete one data using my delete API with the icon onClick event and after that, I simply call my list API but the list is not updated I have to refresh that page or simply double click on my icon then list call updates.
When I debug my code then I notice that API call coming with the response of 304 after deleting the successful message.
This happens only in delete functionality.
Here is Code.
Icon
<i class="zmdi zmdi-delete zmdi-hc-lg" id={data._id} onClick={(e) => this.deletedata(e.target.id)} ></i>
Delete Function
deletedata = (data) => {
debugger;
this.props.DeleteCity(data);<----Delete Api Call
this.props.getcity();<----- Get Api Call
}
Note:-
1. API is made in Node on the backend side and Front side using redux-saga for API calls.
2. And please note that API is not yet Uploaded on any server I am using them in the same system with help of cross-environment setup.
It doesn't happen because it doesn't work asynchronously.
deletedata = async (data) => {
debugger;
await this.props.DeleteCity(data);<----Delete Api Call
this.props.getcity();<----- Get Api Call
}

When attempting to stub a request in Cypress IO (JS) against a React app using fetch, the requests still call through to the server

I'm using Cypress to create some specs against my React app. My react app uses fetch to fetch data from an external api (isomorphic-fetch)
The fetch requests in my app are like so
import fetch from 'fetch'
...
fetch('http://www.external-server.com/ideas.json')
.then((response) => {
if (response.status >= 400) {
}
return response.json().then((result) => {
this._data = result
this._data((ele) => ele.key = ele.id)
});
})
In my Cypress specs, I want my regular specs to hit my lcoahost:3000 to get the initial page (which houses my React app). My react app in turn would normally make an external request (http://www.external-server.com/ideas.json) but in my specs I want to stub out that request and have that endpoint return fake data in my specs only.
The Cypress docs for cy.route() here, describe that I should be able to do something like
cy.server()
cy.route('http://www.external-server.com/ideas.json', [
{
id: 1,
name: 'john'
}
])
I attempted to put this into a beforeEach that runs in the context of my spec (thus running before every spec).
You will note that when I run the specs in the Cypress test running, it appears in the console output that the endpoint SHOULD be stubbed.
However, by examination, I can see that my app is in fact making the request to the real server, and calling the real endpoint (not stubbing it).
I tested several times and I am certain this is the behavior.
I found a solution online I will post below to answer my question
the solution is add to cypress/support/commands.js
this small hack will turn the window fetch into a no-op (disabling it) and will allow the native stubbing in Cypress to work without any alterations.
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
const opts = Object.assign({}, options = {}, {
onBeforeLoad: (window, ...args) => {
window.fetch = null;
if (options.onBeforeLoad) {
return options.onBeforeLoad(window, ...args);
}
},
});
return originalFn(url, opts);
});

Call API resource using meteor

I would like to call an API resource using meteor and React. What I would like to happen is;
load a page
have a form shown to a user
user submits form
use the form data as parameters for the API call via POST
returns the API response to React.
How do I achieve this? Am I on the right track by using Meteor.wrapAsync?
Meteor.wrapAsync wouldn't be neccesary. If you have a button in React. You should keep the fields in the state. React Forms. Then use this code in your component to call a meteor method.
onClick(e){
e.preventDefault();
const { objectToPost } = this.state;
Meteor.call("some_method", objectToPost, (err, res) => { doSmthWithFrontend });
}
The Meteor method will be called async for you and return when the call returns. In this method you can use Meteor Http to achieve what you want.

Is it possible to make a pseudo-global promise rejection handler?

fetch() is a great improvement over the classic XMLhttpRequest() However I was wondering if I add window.addEventListener('unhandledrejection', event => ยทยทยท); to my index.android.js and index.ios.js could I theoretically remove all of my .catch() from my promise chains and make a pseudo global promise rejection handler? I am building a react native app that relies heavily on api calls, many of which are authenticated with user tokens. When a user logs in a token is stored in asynchronous storage, but each token will expire after a certain amount of time. if a user opens the app and unwittingly attempts to make a call that requires authentication with an expired token I would like the user to be routed to the login page regardless of what call was made, or what component the call is in. I currently have each individual promise chain handling unauthenticated calls on their own. Is there a better way to do it?
You could make a custom abstraction on top of fetch, which will provide a way of communicating with API and also have some business logic, which for you case is to request an auth token or make a redirect. Then you use this abstraction in the rest of the code to make API calls. Here is a small example to demonstrate the idea:
export default function request(url, options = {}) {
const req = fetch(url)
.then((response) => {
// Global response handler
// ...
// Hand response down the promise chain
return response;
})
.catch((err) => {
// Global error handler
// Check error status and (make redirect/request auth token)
// Throw error down the promise chain if needed
throw err;
});
// Returns a promise
return req;
}
Then you use it in your code like fetch(), but instead you'll be able to modify and extend it for you needs any time.
request('http://example.com/api/post/1')
.then((response) => {
// "response" has whatever you returned from global handler
})
.catch((err) => {
// "err" is whatever you've thrown from global handler
});

Resources