Reputation: 5477
In React, state is not be updated instantly, so we can use callback in setState(state, callback)
. But how to do it in Redux?
After calling the this.props.dispatch(updateState(key, value))
, I need to do something with the updated state immediately.
Is there any way I can call a callback with the latest state like what I do in React?
Upvotes: 121
Views: 140398
Reputation: 79
As a simple solution you can use: redux-promise
But if you using redux-thunk, you should do sth like this:
function addCost(data) {
return dispatch => {
var promise1 = new Promise(function(resolve, reject) {
dispatch(something);
});
return promise1;
}
}
Upvotes: 2
Reputation: 3304
redux
's dispatch
returns a promise that you can chain off from like so.
const submissionPromise: any = dispatch(submitFundRequest())
submissionPromise
.then((response: any) => {
if(response.error) {
return console.log('There was an error', response)
}
Swal.fire({
title: 'Submission',
text: 'You have successfully submitted the requisition'
})
})
.catch((err: any) => {
console.log('Submission failed', err)
})
response.error
is only set if the thunk was rejected. In your submitFundRequest
thunk, you can do something like this to reject.
export const submitFundRequest = createAsyncThunk(
'fundRequest/submitFundRequest',
async function submit(payload, thunkAPI) {
try {
...
} catch(e: any) {
const error = { message: e.response.statusMessage }
return thunkAPI.rejectWithValue(error)
}
}
)
Upvotes: 0
Reputation: 4101
With Hooks API:
useEffect
with the prop as input.
import React, { useEffect} from 'react'
import { useSelector } from 'react-redux'
export default function ValueComponent() {
const value = useSelector(store => store.pathTo.value)
useEffect(() => {
console.log('New value', value)
return () => {
console.log('Prev value', value)
}
}, [value])
return <div> {value} </div>
}
Upvotes: 40
Reputation: 10391
component should be updated to receive new props.
there are ways to achieve your goal:
1. componentDidUpdate check if value is changed, then do something..
componentDidUpdate(prevProps){
if(prevProps.value !== this.props.value){ alert(prevProps.value) }
}
2. redux-promise ( middleware will dispatch the resolved value of the promise)
export const updateState = (key, value)=>
Promise.resolve({
type:'UPDATE_STATE',
key, value
})
then in component
this.props.dispatch(updateState(key, value)).then(()=>{
alert(this.props.value)
})
2. redux-thunk
export const updateState = (key, value) => dispatch => {
dispatch({
type: 'UPDATE_STATE',
key,
value,
});
return Promise.resolve();
};
then in component
this.props.dispatch(updateState(key, value)).then(()=>{
alert(this.props.value)
})
Upvotes: 140
Reputation: 3411
You can use a thunk with a callback
myThunk = cb => dispatch =>
myAsyncOp(...)
.then(res => dispatch(res))
.then(() => cb()) // Do whatever you want here.
.catch(err => handleError(err))
Upvotes: 3
Reputation: 9746
The most important point about React is one-way data flow. In your example that means, that dispatching an action and state change handling should be decoupled.
You shouldn't think like "I did A
, now X
becomes Y
and I handle it", but "What do I do when X
becomes Y
", without any relation to A
. Store state can be updated from mutiple sources, in addition to your component, Time Travel also can change state and it will not be passed through your A
dispatch point.
Basically that means that you should use componentWillReceiveProps
as it was proposed by @Utro
Upvotes: 17
Reputation: 19113
You could use subscribe
listener and it will be called when an action is dispatched. Inside the listener you will get the latest store data.
http://redux.js.org/docs/api/Store.html#subscribelistener
Upvotes: 6