0
votes

I'm a newbie to React and I'm creating react CRUD application with Collaboration of following Redux-Form, React Routing, Semantic UI and Redux Store technologies

So I able to complete react routing part, now I'm stucking on adding form object to redux store.

enter image description here

This is my folder structure

enter image description here

This is my AddStudents.Js file

import React, { Component } from "react";
import "../App.css";
import { Field, reduxForm } from "redux-form";
import { allActions } from "../Actions/AllActions";

export class AddStudents extends React.Component {
  renderError({ error, touched }) {
    if (touched && error) {
      return (
        <div className="ui error message">
          <div className="header">{error}</div>
        </div>
      );
    }
  }

  handleChange(e) {
    this.setState({ ...this.state, [e.target.name]: e.target.value });
  }

  constructor(props) {
    super(props);
    this.state = {
      firstName: "",
      lastName: ""
    };
  }

  renderInput = ({ label, input, meta }) => {
    console.log(meta);
    const className = `field ${meta.error && meta.touched ? "error" : " "}`;
    return (
      <div className={className}>
        <label>{label}</label>
        <input {...input} autoComplete="off"></input>
        {this.renderError(meta)}
      </div>
    );
  };

  onSubmit(student) {
    console.log("form was submitted!");
    console.log(student);
    const { dispatch } = this.props;
    dispatch(allActions.addStudents(this.state));
    this.setState({
      firstName: "",
      lastName: ""
    });
  }

  render() {
    const { handleSubmit } = this.props;
    return (
      <div className="ui container">
        <span></span>
        <h2>Add Student</h2>
        <form
          onSubmit={handleSubmit(this.onSubmit.bind(this))}
          className="ui form error"
        >
          <Field
            name="firstName"
            component={this.renderInput}
            label="First Name"
            value={this.state.firstName}
            onChange={e => this.handleChange(e)}
          ></Field>
          <Field
            name="lastName"
            component={this.renderInput}
            label="Last Name"
            value={this.state.lastName}
            onChange={e => this.handleChange(e)}
          ></Field>
          <button className="ui button primary">Submit</button>
        </form>
      </div>
    );
  }
}

const validate = formValues => {
  const errors = {};
  if (!formValues.firstName) {
    errors.firstName = "Enter your First Name ...";
  }
  if (!formValues.lastName) {
    errors.lastName = "Enter your Last Name ...";
  }

  return errors;
};

function mapStateToProps(state) {
  const { student } = state.addStudents;
  return {
    student
  };
}

export default reduxForm({
  form: "OurForm",
  validate,
  mapStateToProps
})(AddStudents);

This is AllActions.js

import { allConstants } from "../Constants/AllConstants.js";
import { allServices } from "../Services/AllServices.js";

export const allActions = {
  addStudents,
  viewStudents,
  editStudents
};

function addStudents(student) {
  return dispatch => {
    dispatch(request(student));
    allServices.addStudents(student);
    dispatch(success(student));
  };
  function request(student) {
    return { type: allConstants.ADD_STUDENT_REQUEST, student };
  }
  function success(student) {
    return { type: allConstants.ADD_STUDENT_SUCCESS, student };
  }
  function failure(error) {
    return { type: allConstants.ADD_STUDENT_FAILURE, error };
  }
}

function viewStudents() {
  return dispatch => {
    dispatch(request());
    var students = allServices.viewStudents();
    dispatch(success(students));
  };
  function request() {
    return { type: allConstants.VIEW_ALL_STUDENTS_REQUEST };
  }
  function success(students) {
    return { type: allConstants.VIEW_ALL_STUDENTS_SUCCESS, students };
  }
  function failure(error) {
    return { type: allConstants.VIEW_ALL_STUDENTS_FAILURE, error };
  }
}

function editStudents(student) {
  return dispatch => {
    dispatch(request(student));
    allServices.editStudents(student);
    dispatch(success(student));
  };
  function request(student) {
    return { type: allConstants.EDIT_STUDENT_REQUEST, student };
  }
  function success(student) {
    return { type: allConstants.EDIT_STUDENT_SUCCESS, student };
  }
  function failure(error) {
    return { type: allConstants.EDIT_STUDENT_FAILURE, error };
  }
}

Here once I filled the form and clicked Submit button, in console log I can see object values binding, but it's not pushing to store, I'm getting the following error

Actions must be plain objects. Use custom middleware for async actions.

Appreciate if can help to fix this issue or recommend proper example to follow.

enter image description here

1
If you are following any tutorial, redux-form is deprecated, use formik or github.com/final-form/react-final-form#-react-final-form instead - Rikin
@Kelum can you post the code of you actions AllActions - TRomesh
@TRomesh thanks. I included the AllActions.Js file here - Kelum

1 Answers

1
votes

request(student) is an action creator that returns a function as an action. This is only possible if you're using the thunk middleware. You will have to install the package and configure you store like below

EDIT

Try doing some changes like this in you store(make sure you install the redux-thunk and redux-logger)

import { createStore, applyMiddleware, compose } from "redux";
import thunkMiddleware from "redux-thunk";
import { createLogger } from "redux-logger";
import rootReducer from "../Reducers";

const loggerMiddleware = createLogger();

const Compose = compose(
  applyMiddleware(thunkMiddleware, loggerMiddleware),
  window.__REDUX_DEVTOOLS_EXTENSION__()
);

const store = createStore(rootReducer, Compose);

export default store;

In your index.js add this

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "./Components/App";
import Store from "./Helper/Store";

ReactDOM.render(
  <Provider store={Store}>
    <App></App>
  </Provider>,
  document.querySelector("#root")
);

In the code that you have provided in your github link you haven't used the store(with thunk middleware) even though you have created it.