Here is my function in songAction.js
export function createSong(title, url, token) {
axios.defaults.headers.common['Authorization'] = token
return function (dispatch) {
axios.post('http://localhost:8080/api/song/create', {
title,
link: url
})
.then((response) => {
console.log('the response was', response)
if(response.data.success){
dispatch({type: "CREATE_SONG_FULFILLED", payload: response.data.song})
} else {
dispatch({type: "CREATE_SONG_REJECTED", payload: response.data})
}
})
.catch((err) => {
dispatch({type: "CREATE_SONG_REJECTED", payload: err})
})
}
}
I want to be able to return a promise after dispatching so I can use the function like this inside a component -
createSong(title, url, token)
.then((result) =>{
// do stuff with result
})
I know I can pass in a callback to make this work async.. but I want to use ES6 features of promises. And I'm a little confused how I can do this.
If you want to go full ES6 you should use the async/await
syntax. This eliminates the need to deal with promises at all.
export function createSong (title, url, token) {
axios.defaults.headers.common['Authorization'] = token
return async (dispatch) => {
try {
const response = await axios.post('http://localhost:8080/api/song/create', {
title,
link: url
})
console.log('the response was', response)
if (response.data.success) {
dispatch({type: 'CREATE_SONG_FULFILLED', payload: response.data.song})
} else {
dispatch({type: 'CREATE_SONG_REJECTED', payload: response.data})
}
} catch (err) {
dispatch({type: 'CREATE_SONG_REJECTED', payload: err})
}
}
}
The anonymous function returned by createSong
is marked with the new async
keyword. This means that the anonymous function will now return an implicit Promise.
The async
keyword also allows you to use await
in the body of the function so you can await
the async call to axios.post
and so treat it as if it were a synchronous call.
Another advantage is that you can go back to using normal try / catch
blocks. These are actually resolving and rejecting the implicit promise behind the scenes but they act in the normal way.
Because the anonymous function is actually returning a Promise, higher up the call chain, wherever you call the createSong(...)
function, you can also use the async / await
syntax ... and so on. No more callbacks, and no more explicit Promise handling.
First of all, you need to return the axios
call.
...
return function (dispatch) {
return axios.post('http://localhost:8080/api/song/create', {
title,
link: url
})
...
Your createSong
function is returning another function (so it's a curried function).
Therefore,
createSong(title, url, token)(dispatch)
.then(()=>{
// something
})
looks to me pretty valid.
I think that it isn't very 'React' way to use return values of dispatched actions.
There is a better way how to solve 'complex' situations like this using Redux Saga , example here .
Although, I used returned values by dispatched actions in this way in the past:
export const updatePage = (id, batch) => {
return dispatch => {
dispatch({
type: 'UPDATE_PAGE',
payload: {
id
}
})
// Make an API call
return requestUpdatePages(
id, batch
).then(data => {
// When API call is successful
return dispatch({
type: 'UPDATE_PAGE_SUCCESS',
payload: {
id,
data
})
})
.catch(error => {
// When API call fails
return dispatch({
type: 'UPDATE_PAGE_FAIL',
payload: {
error,
id
},
error: true
})
})
}
}
// After dispatch is bound to action creators
// you can use it like this
handleClick(id) {
const { updatePage } = this.props
updatePage(id).then(action => {
if(action.type === 'UPDATE_PAGE_SUCCESS') {
console.log('Whee, page has been updated!', action.payload.data)
} else {
console.error('Something went wrong :-( ', action.payload.error)
}
})
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.