Lets say I have a functin that calls api:
export default function AuthApi({url, method, headers, data}={}){
return (dispatch, getState) => {
fetch(url, {
method: method || null,
headers: headers || null,
body: form || null,
}).then(function(response) {
return response.json();
}).then(function(response){
console.log(response)
})
}
}
Now I want to call this api somewhere in action:
dispatch(AuthApi({url: "some_url", method: "POST", data: data}))
console.log("called api")
dispatch(userInfo(response))
console.log(getState())
router.pushState(null, '/profile')
Here I am calling the api with dispatch and then dispatch(userInfo) .
I assume my dispatch(userInfo()) function to be called after all the processing in dispatch(AuthApi())
But here it goes into AuthApi() but without completing it it start to call other function or process
How can I only call my other function or logic or ever console.log() after dispatch(AuthApi()) is completely finished.
Thank you
You can use Promises, they work perfectly well with thunkMiddleware:
dispatch(AuthApi({url: "some_url", method: "POST", data: data})).then((response) => {
dispatch(userInfo(response))
})
More examples here
UPDATE
You should also modify action to return promise.
export default function AuthApi({url, method, headers, data}={}){
return (dispatch, getState) => {
return fetch(url, {
method: method || null,
headers: headers || null,
body: form || null,
}).then(function(response) {
return response.json();
})
}
}
Related
I have a function within a class that makes a call and returns a promise object with data. I do get the data back the issue is I cannot figure out how to make the call wait till all of the data is returned at the moment it only returns a few lines of data and cuts off the rest of the return.
async callCurl(postFields) {
this.postFields = postFields;
const response = await client
.request(
{
url: this.url,
method: "POST",
debug: true,
body: "folderGuid=" + this.postFields,
headers: {
"content-type": "application/x-www-form-urlencoded",
},
resolve: true,
},
"username",
"password",
"",
"domain"
)
.then((response) => {
console.log(response.body);
})
.catch(function (error) {
console.log(error);
});
//return response;
}
I have the following Login function:
export function Login(username, password) {
return dispatch => {
dispatch(loginBegin());
axios({
method: 'post',
url: 'api/User/Login',
data: { username, password },
}).then(response => {
if (response.data !== null) {
console.log('success: Login is successful');
dispatch(loginSuccess(response.data));
}
}).catch(error => { dispatch(loginFailure(error.response.data.message)) });
}
}
I call this function as follows in the Login component:
function FormSubmitHandle(values) {
setFormSubmitted(true);
props.login(values.username, values.password)
.then((login_succeeded) => {
console.log('YESSSS');
console.log(login_succeeded);
});
}
However, .then() part is not working. It does not print out anything.
Any ideas why this is happening?
You should return:
return axios({
method: 'post',
url: 'api/User/Login',
data: { username, password },
}).then(response => { ....
Take a look here: is it considered good practice to pass callBacks to redux async action?
Although, I wonder what kind of thing you wish to do with that. When dealing with flux based patterns (such as Redux), we should keep the data flow in one direction (keep that in mind)
you can change it like below:
export function Login(username, password) {
return async (dispatch) => {
dispatch(loginBegin());
try{
let res = await axios({
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json'
},
'method': 'post',
'url': 'api/User/Login',
data: { username, password },
});
console.log('success: Login is successful');
dispatch(loginSuccess(res));
}
catch(error) { dispatch(loginFailure(error.response.data.message)) });
}
then you can use it like below:
cosnt FormSubmitHandle = async (values)=> {
setFormSubmitted(true);
let res = awiat props.login(values.username, values.password);
console.log('YESSSS');
}
I'm making a GET request with Axios in a React-Redux project, and I get the following error:
TypeError: "config.method.toLowerCase is not a function"
request Axios.js:43
wrap bind.js:11
apiCall api.js:32
apiCall api.js:29
... ...
api.js is a file from my own project. bind.js and Axios.js is from the Axios library. This is my api function:
export function apiCall(method, path, data){
let url = backendDomain + path
let config = {
method: [method],
url: [url],
data : [data],
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
}
}
return new Promise((resolve, reject)=>{
return axios(config).then(res=> {
return resolve(res.data)
}).catch(err => {
return reject(err.response);
})
})
The function that makes use of apiCall() is this function:
export function authUser(url, userData, method){
return (dispatch) => {
return new Promise((resolve, reject)=>{
return apiCall(method, "/"+`${url}`, userData)
.then((data) => {
...
resolve();
})
.catch(err=>{
...
reject();
})
})
}
}
Do you think there's something wrong with my code or is there something wrong with the library? When I use authUser to dispatch my action (for Redux State), I double checked that "method" is a String, I console.logged typeof method in api.js, and it returned string.
Edit:
I tried calling toString() to the method parameter passed into apiCall(), but it didn't work:
let reMethod = method.toString();
const config = {
method: [reMethod],
url: [url],
data : [data],
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
}
}
As mentioned in my comment, you're providing an array when axios expects a string:
const config = {
method: reMethod,
url: url,
data : data,
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
}
}
I am trying to get the value of asset:
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
console.log(asset);
The result is:
[object Promise]
How do I get the returned value from the request?
Using async and await is a practical way -
function axios(query) { // fake axios, for demo
return new Promise (r =>
setTimeout(r, 1000, { asset: query.params.assetId })
)
}
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
})
}
async function main() { // async
const asset = await getAssetInformation (11022) // await
console.log(asset)
}
main()
// 1 second later ...
// { asset: 11022 }
You will need to use .then function.
const asset = getAssetInformation(11002)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Promises return another promise.
The way to unpack and work with a promise is through the .then() function, which will run after the promise returns.
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
Asset here is a promise, you want to use a then on it to get the value.
Instead of..
const asset = getAssetInformation(11002);
use
getAssetInformation(11002)
.then((response) => {
//What you returned will be here, use response.data to get your data out.
} )
.catch((err) => {
//if there is an error returned, put behavior here.
})
i'm training to do an axios call with promise, but wihtout success
import axios from "axios";
export class ContiService {
getConti() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
const URL =
process.env.REACT_APP_BASE_PATH + process.env.REACT_APP_RESOURCE_CONTI;
console.log(URL);
return axios(URL, {
method: "GET",
headers: { "content-type": "application/json", preferences: "" },
});
resolve(/* ??? */);
}, 300);
});
}
}
export default class Posizionecliente extends Component {
constructor(props) {
super(props);
this.contiService = new ContiService();
this.state = {
conti: [],
};
}
componentDidMount() {
this.contiService.getConti().then(r => this.setState({ conti: r.data.conti }));
}
}
How can complete this with promise?
The call does not work at the moment, where should I place resolve?
The key here is to realize that axios itself returns a promise. So there are a couple of ways to approach this.
In either case, there is no need for setTimeout.
return new Promise(function(resolve, reject) {
const URL = process.env.REACT_APP_BASE_PATH+process.env.REACT_APP_RESOURCE_CONTI;
axios(URL, {
method: 'GET',
headers: {'content-type': 'application/json', 'preferences' : ''}
}
)
.then(response=> resolve(response.data))
.catch(err => reject(err))
}
Or alternately, and perhaps more clearly, simply return the axios call itself, which will return the promise and allow your component logic to handle state accordingly
getConti() {
const URL = process.env.REACT_APP_BASE_PATH+process.env.REACT_APP_RESOURCE_CONTI;
return axios(URL, {
method: 'GET',
headers: {'content-type': 'application/json', 'preferences' : ''}
}
)
}
You don't have to change your component logic (except perhaps to handle promise rejections).
this.contiService.getConti().then(r => this.setState({ conti: r.data.conti }));
The .then will handle the successful completion of the axios call.
Here's a good read on Promise Chaining. See in particular, the section on returning promises.
If a promise is resolved with another promise, it will adopt the new one. Therefore:
const request = axios(URL, etc);
resolve(request);
Don't return. setTimeout doesn't do anything with the return value of the function it executes.