Search code examples
reactjsreduxreducersreact-final-form

Is there a way to use Redux actions and reducer with react-final-form?


I have a form created through regular React class component which I am trying to migrate to use 'react-final-form'. Everything looks ok but not able to find a way to use reducers with 'react-final-form'

Initially, I used bindActionCreators from react to map Dispatch To Props. So, it used to make a call to action file and everything was fine. Not sure if there is anyway to use the same functionality. I tried to call action directly from onSubmit but dispatch is undefined there. I even couldn't find any tutorial that covers this part.

signup Form:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {Link} from 'react-router-dom'
import {Form, Field} from 'react-final-form';


// custom modules
import { submitEmail } from '../../actions/submitEmail';

import '../../styles/custom.css';


//Form through react-final-form
const renderInput = ({input, meta}) => (
    <input {...input} type="text" errorMessage={meta.touched && meta.error} />
);

const onSubmit = values => {
    debugger;
    submitEmail('/freeTrial', values);
    console.log("put request sent for trial ")
    alert(JSON.stringify(values))
};

const required = v => {
    console.log("v....: ", v);
    if (!v || v === ''){
        return 'This field is required';
    }

    return undefined;
};


const SendEmailInfo = () =>  (
    <Form
        onSubmit={onSubmit}
        render={({handleSubmit, invalid}) => (
            <div>
                <h2>Request 30 days Free Trial</h2>
                <form  onSubmit={handleSubmit} >
                    <Field name="customer-id"
                           component={renderInput}
                           validate={required} />
                    <button type="submit" disabled={invalid} > Submit </button>
                </form>
            </div>
        )}
    />
);

const mapDispatchToProps = dispatch => {
    return bindActionCreators(
        { submitEmail }, dispatch);
};


export default connect(null, mapDispatchToProps)(SendEmailInfo)

Submit Email

import { API_URL } from '../global';

export const makeAPIRequestToSendEmail = () => {
    return {
        type: 'MAKE_API_REQUEST_TO_SEND_EMAIL'
    };
};

export const clearEmailDetails = () => {
    return {
        type: 'CLEAR_EMAIL_DETAILS'
    };
};

export const receivedResponse = () => {
    return {
        type: 'RECEIVED_RESPONSE'
    };
};

export const sentEmail = data => {
    return {
        type: 'SENT_EMAIL',
        data
    };
};

export const errorEmail = () => {
    return {
        type: 'ERROR_EMAIL'
    };
};

export function submitEmail(url, data) {
    return dispatch => {
        dispatch(makeAPIRequestToSendEmail());
        dispatch(clearEmailDetails());
        return fetch(API_URL + url, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ data })
        })
            .then(response => response.json())
            .then(emailMessage => {
                dispatch(receivedResponse());
                console.log(emailMessage);
                dispatch(sentEmail(emailMessage));
            })
            .catch(err => dispatch(errorEmail()));
    }
}

I would like to use actions and reducers and just let it take care of all API requests. Please let me know if you have any suggestions to solve this puzzle.


Solution

  • All React Final Form cares about is that you give it an onSubmit that returns a Promise. I have written a library to do this with Redux actions that might fit your specific needs?

    React Redux Promise Listener