Reputation: 2746
I want to set form loading state (spinner icon, disable input) when the user submits the form, and clear that state when the action completes or fails. Currently I am storing this state in my store, which involves creating an action creator and reducer, which is annoying for a few reasons:
this.setState
Essentially I want to do this within my form component:
handleFormSubmitted() {
this.setState({ isSaving: true })
this.props.dispatchSaveForm({ formData: this.props.formData })
.finally(() => this.setState({ isSaving: false }))
}
Upvotes: 0
Views: 1718
Reputation: 13071
You can't do that with redux-saga. What you are trying to do there goes against the basic principles of redux-saga.
redux-saga
aims to be reactive by treating actions like events that describe what's happening in your app... So that other sagas (usually "watchers" using take
) or the rootReducer can subscribe to those actions/events and do what they need to do...
Because of that redux-saga
-unlike redux-thunk
and redux-promise
-
doesn't change the behaviour of the dispatch
method... So, with redux saga when you dispatch, you dispatch, and the reducers and the sagas are subscribed to the dispatched actions. But the dispatch
method won't return a promise like it happens when you use other middlewares/store-enhancers.
So, the only way that redux-saga
has to let the rest of the app know that the request of your form has finished is by dispatching an action (using the put
effect) whenever that request finishes or errors, right? So, how could you possibly know directly from inside the component if a specific action has been dispatched?
Unless you make your own middleware (or you use a separate one) with a connector component: there is no way for you to subscribe to concrete actions inside a component.
Sure, you could access the context directly in order to get a hold of your redux store, and then you could use the redux subscribe
method directly, but the listener function won't tell you what's the action that got dispatched. It will just get invoked when an action (any action) gets dispatched... maybe you could check if some property of the state has changed, but that's insane. So, unless you want to go down that route, which is crazy: you can't do that using redux-saga.
If you wanted to do something like that (which IMHO is not a very good idea) you would have to do it without using redux-saga. A possible way to do it could be something along the lines of:
handleFormSubmitted() {
this.setState({ isSaving: true })
yourFetchCall({ formData: this.props.formData })
.then(payload => this.props.dispatchFormSaved(payload))
.catch(error => this.props.dispatchSavingFormErrored(error))
.finally(() => this.setState({ isSaving: false }))
}
Upvotes: 6