How can I make a discount for submitting an action and also return a promise?
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 the promise after dispatch, so I can use a function like this inside the component -
createSong(title, url, token)
.then((result) =>{
// do stuff with result
})
I know I can pass a callback to make this async work .. but I want to use ES6 promises features. And I am a little confused how I can do this.
source to share
If you want to go through full ES6 you must use the syntax async/await
. This removes 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 createSong
is marked with a new keyword async
. This means that the anonymous function will now return an implicit promise.
The keyword async
also allows you to use await
functions in the body so that you can await
call asynchronously axios.post
, and therefore treat it as if it were a synchronous call.
Another advantage is that you can revert to using regular blocks try / catch
. They actually allow and deny the implicit promise behind the scenes, but they operate in the usual way.
Since the anonymous function actually returns a Promise, above the call chain, wherever you call the function createSong(...)
, you can also use the syntax async / await
... and so on. No more callbacks and more explicit promise handling.
source to share
First of all, you need to return the challenge axios
.
...
return function (dispatch) {
return axios.post('http://localhost:8080/api/song/create', {
title,
link: url
})
...
Your function createSong
returns another function (so this is a curric function).
Hence,
createSong(title, url, token)(dispatch)
.then(()=>{
// something
})
looks pretty correct.
source to share
I think this is not a very "React" way of using the return values โโof dispatched actions.
There is a better way to deal with tricky situations like Redux Saga , for example here .
Although, in the past I've used return values โโby sending actions like this:
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)
}
})
}
source to share