erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
12.01k stars 2.5k forks source link

fieldArray doesn't work #1282

Open k130130 opened 7 years ago

k130130 commented 7 years ago
  1. reference: https://react-redux.herokuapp.com/survey I want to add "phones" in FieldArray.
  2. error message: warning.js:45 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of SurveyForm.warning @ warning.js:45createElement @ ReactElementValidator.js:221render @ SurveyForm.js:116_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js:587_renderValidatedComponent @ ReactCompositeComponent.js:607ReactCompositeComponent__renderValidatedComponent @ ReactPerf.js:66mountComponent @ ReactCompositeComponent.js:220ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountChildren @ ReactMultiChild.js:241_createContentMarkup @ ReactDOMComponent.js:591mountComponent @ ReactDOMComponent.js:479mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37mountComponent @ ReactCompositeComponent.js:225ReactCompositeComponent_mountComponent @ ReactPerf.js:66mountComponent @ ReactReconciler.js:37_mountChildByNameAtIndex @ ReactMultiChild.js:474_updateChildren @ ReactMultiChild.js:378updateChildren @ ReactMultiChild.js:326_updateDOMChildren @ ReactDOMComponent.js:871updateComponent @ ReactDOMComponent.js:700receiveComponent @ ReactDOMComponent.js:645receiveComponent @ ReactReconciler.js:87updateChildren @ ReactChildReconciler.js:84_reconcilerUpdateChildren @ ReactMultiChild.js:216_updateChildren @ ReactMultiChild.js:351updateChildren @ ReactMultiChild.js:326_updateDOMChildren @ ReactDOMComponent.js:871updateComponent @ ReactDOMComponent.js:700receiveComponent @ ReactDOMComponent.js:645receiveComponent @ ReactReconciler.js:87_updateRenderedComponent @ ReactCompositeComponent.js:562_performComponentUpdate @ ReactCompositeComponent.js:544updateComponent @ ReactCompositeComponent.js:473ReactCompositeComponent_updateComponent @ ReactPerf.js:66receiveComponent @ ReactCompositeComponent.js:405receiveComponent @ ReactReconciler.js:87_updateRenderedComponent @ ReactCompositeComponent.js:562_performComponentUpdate @ ReactCompositeComponent.js:544updateComponent @ ReactCompositeComponent.js:473ReactCompositeComponent_updateComponent @ ReactPerf.js:66receiveComponent @ ReactCompositeComponent.js:405receiveComponent @ ReactReconciler.js:87_updateRenderedComponent @ ReactCompositeComponent.js:562_performComponentUpdate @ ReactCompositeComponent.js:544updateComponent @ ReactCompositeComponent.js:473ReactCompositeComponent_updateComponent @ ReactPerf.js:66receiveComponent @ ReactCompositeComponent.js:405receiveComponent @ ReactReconciler.js:87_updateRenderedComponent @ ReactCompositeComponent.js:562_performComponentUpdate @ ReactCompositeComponent.js:544updateComponent @ ReactCompositeComponent.js:473ReactCompositeComponent_updateComponent @ ReactPerf.js:66receiveComponent @ ReactCompositeComponent.js:405receiveComponent @ ReactReconciler.js:87_updateRenderedComponent @ ReactCompositeComponent.js:562_performComponentUpdate @ ReactCompositeComponent.js:544updateComponent @ ReactCompositeComponent.js:473ReactCompositeComponent_updateComponent @ ReactPerf.js:66performUpdateIfNecessary @ ReactCompositeComponent.js:421performUpdateIfNecessary @ ReactReconciler.js:102runBatchedUpdates @ ReactUpdates.js:129perform @ Transaction.js:136perform @ Transaction.js:136perform @ ReactUpdates.js:86flushBatchedUpdates @ ReactUpdates.js:147ReactUpdates_flushBatchedUpdates @ ReactPerf.js:66closeAll @ Transaction.js:202perform @ Transaction.js:149batchedUpdates @ ReactDefaultBatchingStrategy.js:62enqueueUpdate @ ReactUpdates.js:176enqueueUpdate @ ReactUpdateQueue.js:24enqueueSetState @ ReactUpdateQueue.js:190ReactComponent.setState @ ReactComponent.js:65(anonymous function) @ ReduxAsyncConnect.js:213 invariant.js:39 Uncaught (in promise) Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of SurveyForm.(…)
  3. My code for SurveyForm.js:

import React, {Component, PropTypes} from 'react'; import {Field, FieldArray, reduxForm} from 'redux-form'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import surveyValidation from './surveyValidation'; import * as surveyActions from 'redux/modules/survey';

function asyncValidate(data, dispatch, {isValidEmail}) { if (!data.email) { return Promise.resolve({}); } return isValidEmail(data); } @connect(() => ({}), dispatch => bindActionCreators(surveyActions, dispatch) ) @reduxForm({ form: 'survey', fields: ['name', 'email', 'occupation', 'currentlyEmployed', 'sex', 'member'], fieldArray: ['members'], validate: surveyValidation, asyncValidate, asyncBlurFields: ['email'] })

export default class SurveyForm extends Component { static propTypes = { active: PropTypes.string, asyncValidating: PropTypes.bool.isRequired, fields: PropTypes.object.isRequired, fieldArray: PropTypes.array, dirty: PropTypes.bool.isRequired, handleSubmit: PropTypes.func.isRequired, resetForm: PropTypes.func.isRequired, invalid: PropTypes.bool.isRequired, pristine: PropTypes.bool.isRequired, valid: PropTypes.bool.isRequired }

render() { const { asyncValidating, dirty, fields: {name, email, occupation, currentlyEmployed, sex}, fieldArray: {members}, active, handleSubmit, invalid, resetForm, pristine, valid } = this.props; const styles = require('./SurveyForm.scss');

const renderInput = (field, label, showAsyncValidating) =>
  <div className={'form-group' + (field.error && field.touched ? ' has-error' : '')}>
    <label htmlFor={field.name} className="col-sm-2">{label}</label>
    <div className={'col-sm-8 ' + styles.inputGroup}>
      {showAsyncValidating && asyncValidating && <i className={'fa fa-cog fa-spin ' + styles.cog}/>}
      <input type="text" className="form-control" id={field.name} {...field}/>
      {field.error && field.touched && <div className="text-danger">{field.error}</div>}
      <div className={styles.flags}>
        {field.dirty && <span className={styles.dirty} title="Dirty">D</span>}
        {field.active && <span className={styles.active} title="Active">A</span>}
        {field.visited && <span className={styles.visited} title="Visited">V</span>}
        {field.touched && <span className={styles.touched} title="Touched">T</span>}
      </div>
    </div>
  </div>;

const renderField = props => (
{props.touched && props.error && {props.error}}

);

const renderMembers = ({ fields }) => (

);

return (
  <div>
    <form className="form-horizontal" onSubmit={handleSubmit}>
      {renderInput(name, 'Full Name')}
      {renderInput(email, 'Email', true)}
      {renderInput(occupation, 'Occupation')}
      <FieldArray name="members" component={renderMembers}/>
      <div className="form-group">
        <label htmlFor="currentlyEmployed" className="col-sm-2">Currently Employed?</label>
        <div className="col-sm-8">
          <input type="checkbox" id="currentlyEmployed" {...currentlyEmployed}/>
        </div>
      </div>
      <div className="form-group">
        <label className="col-sm-2">Sex</label>
        <div className="col-sm-8">
          <input type="radio" id="sex-male" {...sex} value="male" checked={sex.value === 'male'}/>
          <label htmlFor="sex-male" className={styles.radioLabel}>Male</label>
          <input type="radio" id="sex-female" {...sex} value="female" checked={sex.value === 'female'}/>
          <label htmlFor="sex-female" className={styles.radioLabel}>Female</label>
        </div>
      </div>
      <div className="form-group">
        <div className="col-sm-offset-2 col-sm-10">
          <button className="btn btn-success" onClick={handleSubmit}>
            <i className="fa fa-paper-plane"/> Submit 4
          </button>
          <button className="btn btn-warning" onClick={resetForm} style={{marginLeft: 15}}>
            <i className="fa fa-undo"/> Reset 4
          </button>
        </div>
      </div>
    </form>

    <h4>Props from redux-form 4</h4>

    <table className="table table-striped">
      <tbody>
      <tr>
        <th>Active Field</th>
        <td>{active}</td>
      </tr>
      <tr>
        <th>Dirty</th>
        <td className={dirty ? 'success' : 'danger'}>{dirty ? 'true' : 'false'}</td>
      </tr>
      <tr>
        <th>Pristine</th>
        <td className={pristine ? 'success' : 'danger'}>{pristine ? 'true' : 'false'}</td>
      </tr>
      <tr>
        <th>Valid</th>
        <td className={valid ? 'success' : 'danger'}>{valid ? 'true' : 'false'}</td>
      </tr>
      <tr>
        <th>Invalid</th>
        <td className={invalid ? 'success' : 'danger'}>{invalid ? 'true' : 'false'}</td>
      </tr>
      </tbody>
    </table>
  </div>
);

} }

jameelahuq commented 7 years ago

I'm having the same issue. I can't even render a one-line div using <FieldArray />