Reputation: 67
on a button click I dispatch an action to make a get request , I wanna wait for the request to complete before I continue ,whats the right approach to do this? I do dispatch an action based on the result in my saga:
function* workerSaga() {
try {
const response = yield call(fetchCall);
const myData= response.data;
// dispatch a success action to the store
yield put({ type: "API_CALL_SUCCESS", myData});
} catch (error) {
// dispatch a failure action to the store with the error
yield put({ type: "API_CALL_FAILURE", error });
}
But how do I know in the code that did dispatch the request action, that the get request has finished?
thx in advance.
EDIT:
without saga a request would look similar to :
axios.get(myURL)
.then(/*here we know the request has finished*/);
with saga:
this.props.dispatch({type:"API_CALL"})
//here i would like to know the request has finished
Upvotes: 0
Views: 3015
Reputation: 85012
this.props.dispatch({type:"API_CALL"})
//here i would like to know the request has finished
In general, that's not the way redux saga gets used by a component. Instead, your component should be subscribed to the store using react-redux's connect
method, so when API_CALL_SUCCESS
goes through the reducer and the state gets updated, your component will get new props and thus rerenders. If necessary, you can implement a componentDidUpdate
to run some code when the prop changes.
It is possible to do a work around so that you can find out when the work is complete through a promise, but doing so requires introducing more coupling between your component and your saga, so i recommend not to use this for most cases. You can set up your action so that part of its payload is a callback function, and then have the saga call that function. For example:
// In the saga
function* workerSaga(action) {
try {
const response = yield call(fetchCall);
const myData = response.data;
// dispatch a success action to the store
yield put({ type: "API_CALL_SUCCESS", myData});
if (action.callback) {
action.callback(myData);
}
} catch (error) {
// dispatch a failure action to the store with the error
yield put({ type: "API_CALL_FAILURE", error });
}
}
// in the component
componentDidMount() {
this.props.dispatch({ type: 'API_CALL', callback: onFetchSuccess });
}
onFetchSuccess(data) {
}
Or if you want to have a promise, then the callback could be the resolver for a new promise:
componentDidMount() {
const promise = new Promise((resolve) => {
this.props.dispatch({ type: 'API_CALL', callback: resolve });
});
promise.then(data => {
});
}
// or, with async/await:
async componentDidMount() {
const data = await new Promise(resolve =>
this.props.dispatch({ type: 'API_CALL', callback: resolve })
);
}
Upvotes: 3
Reputation: 692
Here's an example using try/catch
function* workerSaga() {
try {
const response = yield call(fetchCall);
if (response.data) { // check based on what the your API returns
const myData= response.data;
// dispatch a success action to the store
yield put({ type: "API_CALL_SUCCESS", myData});
} else {
throw response;
}
} catch (error) {
// dispatch a failure action to the store with the error
yield put({ type: "API_CALL_FAILURE", error });
}
}
without try/catch
function* workerSaga() {
const response = yield call(fetchCall);
if (response.data) { // check based on what the your API returns
const myData= response.data;
// dispatch a success action to the store
yield put({ type: "API_CALL_SUCCESS", myData});
} else {
// dispatch a failure action to the store with the error
yield put({ type: "API_CALL_FAILURE", error });
}
}
Upvotes: 0