Search code examples
reactjsreduxredux-formrecompose

React Higher Order Components syntax


Overview

I am having a hard time understanding the syntax I am finding on the net when it comes to wrapping react components with higher order components in order to access props.

The following example (which works) I am to wrapping the component with

withFireStore => ReduxForms => Connect => Component

export default withFirestore(
    reduxForm({
        form: "createStudents", validate
    })(connect(
          mapStateToProps,
          mapDispatchToProps)(CreateStudentsForm))
);

Background of what I am trying to do

Ultimately I am trying to access props through a Validate function I am using as part of the revalidate.js library. When following the solution from this stackoverflow post, I do not get the props mapped to state from ownProps. I believe this is due to how I an ordering my Higher order components.

Problem

I actually need ReduxForm wrapped by the connect so it can access props I am mapping from redux state.

withFireStore => Connect => ReduxForms => Component

Attempt 1
export default withFirestore(
    (connect(
            mapStateToProps,
            mapDispatchToProps
        )
        (reduxForm({
            form: "createStudents", validate
        }))
        (CreateStudentsForm)
    )
);
Error

Cannot call a class as a function

I thought i had the brackets in the wrong spots, but when I shift them like so I get

Attempt #2
export default withFirestore(
    (connect(
            mapStateToProps,
            mapDispatchToProps
        )
        (reduxForm({
            form: "createStudents", validate
        })
        (CreateStudentsForm))
    )
);
Error

Uncaught Invariant Violation: You must pass a component to the function returned by connect.

Questions

  1. I find chaining functions like this very confusing, is there a better way to write this?
  2. How do I write this so reduxFrom will be wrapped by connect which should give me access to the props within my forms.

Added to question:

CreateStudentForm.js imports

import React, { Component } from "react";
import { reduxForm, Field } from "redux-form";
import {compose} from 'redux';
import { Container, Form, Col, Button } from "react-bootstrap";
import MaterialIcon from '../../material-icon/materialIcon';
import { withFirestore } from "react-redux-firebase";
import { connect } from "react-redux";
import TextInput from "../../forms/textInput";
import { combineValidators, isRequired } from "revalidate";
import { setupStudentForm } from '../../../store/actions/students';

The CreateStudentForm is imported into a Stateful component called modal.js

Modal.js imports

import React, { Component } from "react";
import { connect } from "react-redux";
import { Modal, Button, Row, Col } from "react-bootstrap";
import Aux from '../../hoc/Aux';
import CreateClassForm from "../createClass/createClassForm";
import EditClassForm from "../editClass/editClassForm";
import EditHomeworkForm from "../editHomework/editHomeworkForm";
import CreateHomeworkForm from "../createHomework/createHomeworkForm";
import CreateStudentsForm  from "../createStudents/createStudentsForm";
import { withFirestore } from "react-redux-firebase";

Solution

  • try compose, sth like:

    export default compose(
      withFirestore, 
      reduxForm({
        form: "createStudents", validate
      }),
      connect(
        mapStateToProps,
        mapDispatchToProps
      )
    )(CreateStudentsForm);