Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get syncErrors out of state using redux-form selectors

So I have a redux-form component that has a validate function that returns values with the Field...

const validate = values => {
  const errors = {
    orderHeader: {}
  };

  const orderHeader = values.orderHeader || {};
  if (!orderHeader.orderID) {
    errors.orderHeader.orderID = "Working";
  }
  if (!orderHeader.salesRepID) {
    errors.orderHeader.salesRepID = "Working as well";
  }

  return errors;
}

I'm trying to figure out how to use a selector to return all of the syncError values to an Error manifest component that will list all current errors.

My selector looks like this

const selector = formValueSelector('mainForm')
MainForm = connect(
  state =>
  ({
    syncErrors: getFormSyncErrors('mainForm')(state),
    initialValues: state.account.data,
  }
),
  { load: loadAccount }, // bind account loading action creator
)(MainForm);

logging the following returns undefined...

  render() {
    const { error, handleSubmit, load, pristine, reset, submitting, values, syncErrors } = this.props;
    console.log(syncErrors)

I feel like I'm making a syntax mistake as I would expect this to return the syncErrors section of state as an object... It appears in state correctly under form.mainForm.syncErrors.

Am I completely misunderstanding this? What would be helpful for me to provide?

Here is the component in its entirety...

import React from "react";
import ReactDOM from "react-dom";
import { Row, Col, Container, Form } from 'reactstrap';
import classnames from 'classnames'
import store from "../../../store";
import { connect } from 'react-redux';
import axios from 'axios'
import RemoteSubmitButton from '../../ReduxForms/RemoteSubmitButton'
import { Field, reduxForm, formValueSelector, getFormSyncErrors } from 'redux-form';
import { load as loadAccount } from '../../../reducers/account';
import renderInput from '../../ReduxForms/FormComponents';
import submit from '../../ReduxForms/submit'
//import validate from '../../ReduxForms/validate'

const validate = values => {
  const errors = {
    orderHeader: {}
  };

  const orderHeader = values.orderHeader || {};
  if (!orderHeader.orderID) {
    errors.orderHeader.orderID = "Working";
  }
  if (!orderHeader.salesRepID) {
    errors.orderHeader.salesRepID = "Working as well";
  }

  return errors;
}
const remotejson= "SalesObject.json";

class MainForm extends React.Component {
  constructor(props) {
  super(props)
  this.state = {
    data: null,
    }
  }

  componentDidMount () {
  axios.get('/data/' + remotejson)
    .then((response) => {
    //    console.log(response.data);
       this.setState({data: response.data})
     })
    .catch((error)=>{
       //console.log(error);
    });
  }

  render() {
    const { error, handleSubmit, load, pristine, reset, submitting, values, syncErrors } = this.props;
    console.log({syncErrors})
    return (
        <div style={{ padding: 15 }}>
          <Form onSubmit={handleSubmit}>
            <button type="button" onClick={() => load(this.state.data)}>Load Order</button>
            <Container>
              <Row>
                <Col sm={4}>
                  <Field label="order ID" id="orderID" name="orderHeader.orderID" type="text" component={renderInput} />
                </Col>
                <Col sm={4}>
                  <Field id="salesRepID" name="orderHeader.salesRepID" type="text" component={renderInput} />
                </Col>
              </Row>
            </Container>
            {syncErrors && <strong>{syncErrors}</strong>}
            {error && <strong>{error}</strong>}
          </Form>
          <RemoteSubmitButton />
        </div>
    )
  }
}

    // Decorate with reduxForm(). It will read the initialValues prop provided by connect()
let MainReduxForm = MainForm = reduxForm({
  form: 'mainForm', // a unique identifier for this form
  enableReinitialize: true, // Important after the data load process is moved to redux saga. This should allow for a common sales object to be built
  validate,
  onSubmit: submit // submit function must be passed to onSubmit
})(MainForm);

// You have to connect() to any reducers that you wish to connect to yourself
const selector = formValueSelector('mainForm')
MainReduxForm = connect(
  state =>
  ({
    syncErrors: getFormSyncErrors('mainForm')(state),
    initialValues: state.account.data
  }),
  { load: loadAccount }, // bind account loading action creator
)(MainReduxForm);

export default MainReduxForm; 
like image 778
Shawn Matthews Avatar asked Feb 16 '18 02:02

Shawn Matthews


1 Answers

syncErrors is a keyword that is internally used by redux-form and is not made available as a prop to the form component. You need to pass your syncError to the component with a different name

class MainForm extends React.Component {
  constructor(props) {
  super(props)
  this.state = {
    data: null,
    }
  }

  componentDidMount () {
  axios.get('/data/' + remotejson)
    .then((response) => {
    //    console.log(response.data);
       this.setState({data: response.data})
     })
    .catch((error)=>{
       //console.log(error);
    });
  }

  render() {
    const { error, handleSubmit, load, pristine, reset, submitting, values, synchronousError } = this.props;
    console.log({syncErrors})
    return (
        <div style={{ padding: 15 }}>
          <Form onSubmit={handleSubmit}>
            <button type="button" onClick={() => load(this.state.data)}>Load Order</button>
            <Container>
              <Row>
                <Col sm={4}>
                  <Field label="order ID" id="orderID" name="orderHeader.orderID" type="text" component={renderInput} />
                </Col>
                <Col sm={4}>
                  <Field id="salesRepID" name="orderHeader.salesRepID" type="text" component={renderInput} />
                </Col>
              </Row>
            </Container>
            {synchronousError && <strong>{synchronousError}</strong>}
            {error && <strong>{error}</strong>}
          </Form>
          <RemoteSubmitButton />
        </div>
    )
  }
}

    // Decorate with reduxForm(). It will read the initialValues prop provided by connect()
let MainReduxForm = reduxForm({
  form: 'mainForm', // a unique identifier for this form
  enableReinitialize: true, // Important after the data load process is moved to redux saga. This should allow for a common sales object to be built
  validate,
  onSubmit: submit // submit function must be passed to onSubmit
})(MainForm);

// You have to connect() to any reducers that you wish to connect to yourself
const selector = formValueSelector('mainForm')
MainReduxForm = connect(
  state =>
  ({
    synchronousError : getFormSyncErrors('mainForm')(state), // change name here
    initialValues: state.account.data
  }),
  { load: loadAccount }, // bind account loading action creator
)(MainReduxForm);

export default MainReduxForm;

I made a demo working codesandbox too

like image 68
Shubham Khatri Avatar answered Nov 15 '22 07:11

Shubham Khatri