redux-form-actions-draftjs v1.1.3
redux-form-actions
Redux Form provides way to make asynchronous submit validation, but API can use only promises. For Redux applications, using actions is more natural. Especially when you are using asynchronous flow abstraction like sagas or observables.
Redux Form Actions is wrapper around Redux Form with action driven submit validations.
Installation
npm install --save redux-form-actionsUsage Guide
#1 Declare actions
Declare action types and actions for form handling
export const SUBMIT_CONTACT_FORM = 'SUBMIT_CONTACT_FORM';
export const SUBMIT_CONTACT_OK = 'SUBMIT_CONTACT_OK';
export const SUBMIT_CONTACT_FAILED = 'SUBMIT_CONTACT_FAILED';
export const submitContactForm = (values) => ({
type: SUBMIT_CONTACT_FORM,
payload: value
});
export const submitContactOk = () => ({
type: SUBMIT_CONTACT_OK
});
export const submitContactFailed = (err) => ({
type: SUBMIT_CONTACT_FAILED,
payload: err
});#2 Create Form
Create form component same as with Redux Form, see https://redux-form.com/6.1.1/docs/GettingStarted.md/#step-2
For convenience redux-form-actions re-export all stuff from redux-form so
you can import fields also from redux-form-actions module.
Decorate the form component using reduxForm from redux-form-actions.
import { Field, reduxForm } from 'redux-form-actions';
// ContactForm = ....
export default reduxForm({
form: 'contact' // a unique name for this form
})(ContactForm);#3 Render Form
Put form to your container. Same as with plain Redux Form onSubmit is
called when user submits form, but instead of returning promise we just
dispatch action. In this example action creator is wrapped with dispatch by
standard react-redux connect.
Form submit is resolved when action matching
succeededAction or failedAction type is dispatched.
import * as Actions, { submitContactForm } from '../actions';
class ContactPage extends React.Component {
render() {
return (
<ContactForm
onSubmit={this.props.submitContactForm}
succeededAction={Actions.SUBMIT_CONTACT_OK}
failedAction={Actions.SUBMIT_CONTACT_FAILED}
/>
);
}
}
export default connect(
state => ({}), { submitContactForm }
)(ContactPage);#4 Register middleware
Middleware is essential to handle declared succeededAction and failedActions.
Use middleware in addition to original form reducer.
import { reduxFormMiddleware, reducer as formReducer } from 'redux-form-actions';
const reducers = {
// ... your other reducers here ...
form: formReducer // <---- Mounted at 'form'
}
const store = createStore(
rootReducer,
applyMiddleware(
reduxFormMiddleware
)
);#4 Put all action together
Finally put all together. Use you favorite approach - thunk, saga or observable.
redux-observable epic:
export default action$ => {
return action$
.ofType(Actions.SUBMIT_CONTACT_FORM)
.mergeMap(action => {
const { form, values } = action.payload;
return ajax.post(`/submits/${form}`, values)
.map(submitContactOk)
.catch(submitContactFailed);
});
};Alternatively, same logic, using redux-saga saga:
function* constactFormSaga() {
while (true) {
const action = yield take(Actions.SUBMIT_CONTACT_FORM);
const { form, values } = action.payload;
try {
yield call(FormApi.submit, `/submits/${form}`, values);
yield put(submitContactOk());
} catch (err) {
yield put(submitContactFailed(err));
}
}API Summary
API is same as redux-form except following reduxForm() changes:
onSubmit:
If succeededAction is also declared onSubmit is considered asynchronous and resolved with future action.
Otherwise behave same as plain reduxForm callback.
succeededAction: string | (action) => boolean Action type or predicate. Matching action resolves submit as succeeded.
failedAction: string | (action) => boolean Action type or predicate. Matching action resolves submit as failed.
Like plain Redux Form, you can use options as reduxForm() argument or declare
them as component props.
Immutable JS
redux-form-actions provide Immutable.JS variant in same way as original redux-form.
import { reduxForm } from 'redux-form-actions/immutable';