2017-03-11 11 views
0

2つの異なるエラーが発生しています。Redux connect/reduxFormはレンダリングしません。

最初は、reduxFormメソッドをエクスポートするだけで、コンポーネント/ stateToProps/reduxFormをすべて接続します。私は彼らが未定義の小道具のタイプに失敗したと言います。例えば

function mapStateToProps(state) { 
    const { account, priceBook } = state; 
    const accountId = account.id; 

    return { accountId, priceBook }; 
} 

export default reduxForm({ 
    form: 'createOrder', 
    destroyOnUnmount: false, 
    validate, 
}, mapStateToProps, { 
    getRevShareAction: getRevShare, 
    getPriceBookAction: getPriceBook, 
})(NewOrderFormFour); 

Warning: Failed prop type: The prop `getPriceBookAction` is marked as required in `NewOrderFormFour`, but its value is `undefined`. 

だから私はreduxFormを分離し、反応-再来のconnectメソッドを使用して小道具を接続し、これを修正します。

NewOrderFormFour = reduxForm({ 
    form: 'createOrder', 
    destroyOnUnmount: false, 
    validate, 
}); 

export default connect(mapStateToProps, { 
    getRevShareAction: getRevShare, 
    getPriceBookAction: getPriceBook, 
})(NewOrderFormFour); 

これはというエラーが返されます:私は2番目のインスタンスでreduxFormをコメントアウトし、コンポーネントにそれがレンダリングシンプル<div>タグをレンダリングする場合

Invariant Violation: Component(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object. 

。私はこの問題の原因となるものが不明です。タイプミスや潜在的なエラーのために、コンポーネントを参照しています。何も意味をなさないようです。あなただけのreduxFormとデコレータ関数を作成しましたが、フォームのコンポーネントには適用されませんでした

import React, { PropTypes } from 'react'; 
import { reduxForm, Form, Field } from 'redux-form'; 
import { connect } from 'react-redux'; 

import { getClassName } from '../../utils/forms'; 
import { storeWithExpiration, getOrderTotalCost } from '../../utils/common'; 
import { getRevShare, getPriceBook } from '../../actions/pricing'; 

import DateTimePicker from 'react-widgets/lib/DateTimePicker'; 
import moment from 'moment'; 
import momentLocalizer from 'react-widgets/lib/localizers/moment'; 
momentLocalizer(moment); 

import ConfirmOrderDialog from './ConfirmOrderDialog'; 
import PriceBookTableContainer from '../pricing/PriceBookTableContainer'; 

const formats = [ 
    'MMM d yyyy', 
    'MMM d yy', 
    'd', 
]; 

export class NewOrderFormFour extends React.Component { 

    static propTypes = { 
    accountId: PropTypes.number.isRequired, 
    companyData: PropTypes.object, 
    cancelOrderFunction: PropTypes.func.isRequired, 
    closeDialogFunction: PropTypes.func.isRequired, 
    dataSets: PropTypes.object.isRequired, 
    dialog: PropTypes.object.isRequired, 
    escapeForm: PropTypes.func.isRequired, 
    fetchFieldsetsByIdFunction: PropTypes.func.isRequired, 
    formValues: PropTypes.object, 
    fieldSets: PropTypes.object.isRequired, 
    getPriceBookAction: PropTypes.func.isRequired, 
    getRevShareAction: PropTypes.func.isRequired, 
    handleSubmit: PropTypes.func.isRequired, 
    openDialogFunction: PropTypes.func.isRequired, 
    platformMap: PropTypes.object.isRequired, 
    previousPageFunction: PropTypes.func.isRequired, 
    priceBook: PropTypes.object.isRequired, 
    providerOrderNumber: PropTypes.string.isRequired, 
    providerCustomerNumber: PropTypes.string.isRequired, 
    renderInput: PropTypes.func.isRequired, 
    renderCompanyInfo: PropTypes.func.isRequired, 
    submitFunction: PropTypes.func.isRequired, 
    submitting: PropTypes.bool.isRequired, 
    useCaseMap: PropTypes.object.isRequired, 
    }; 

    createOrderFunction = (params) => { 
    const { openDialogFunction, submitFunction } = this.props; 

    openDialogFunction('confirmOrderDialog'); 
    submitFunction(params); 
    }; 

    handleStartDayChange = (param, startDay) => { 
    const { formValues: { endDay } } = this.props; 
    const endDayDate = new Date(moment(param).add(1, 'y').format()); 
    if (endDayDate) { 
     // endDay.value = endDayDate; 
     endDay.onChange(endDayDate); 
    } 
    return startDay.onChange(param); 
    } 

    handleEndDayChange = (param, endDay) => { 
    return endDay.onChange(param); 
    } 

    // Field manipulation is due to the fact that the calendar picker 
    // requires a date object, but react currently doesn't support 
    // passing objects as form values 
    openConfirmationDialog =() => { 
    const { openDialogFunction } = this.props; 
    let { formValues: { startDay, endDay } } = this.props; 

    const startDayString = JSON.stringify(startDay); 
    startDay = startDayString; 
    const endDayString = JSON.stringify(endDay); 
    endDay = endDayString; 
    openDialogFunction('confirmOrderDialog'); 
    } 

    render() { 
    const { 
     accountId, 
     dataSets, 
     dialog, 
     escapeForm, 
     fieldSets, 
     formValues, 
     formValues: { 
     platformCode, 
     numberOfSeats, 
     numberOfRecords, 
     }, 
     handleSubmit, 
     platformMap, 
     priceBook, 
     useCaseMap, 
     renderInput, 
     renderCompanyInfo, 
     submitting, 
     closeDialogFunction, 
     previousPageFunction, 
    } = this.props; 
    const isCRMTable = platformCode === 'SFDC'; 
    const pricebookData = isCRMTable ? priceBook.get('crmList') : priceBook.get('maList'); 
    const selectedPbData = pricebookData ? pricebookData.map(value => { 
     return { 
     floor: value.get('floor'), 
     min: value.get('min'), 
     max: value.get('max'), 
     }; 
    }).toArray() : null; 

    // If the user opens confirm dialog then cancels, we need to convert start and and dates 
    // from a string back to a date object 
    // Don't convert if dialog open 
    const dialogIsOpen = dialog.get('show'); 
    let { formValues: { startDay, endDay } } = this.props; 
    if (!dialogIsOpen) { 
     if (typeof startDay === 'string' && startDay.length > 0) { 
     startDay = new Date(JSON.parse(startDay)); 
     } 
     if (typeof endDay === 'string' && endDay.length > 0) { 
     endDay = new Date(JSON.parse(endDay)); 
     } 
    } 

    return (
     <div className="modal-wrap"> 
     <div className="container"> 
      <div className="card card-block"> 
      <span className="pull-right"> 
       <button 
       type="button" 
       className="btn btn-secondary escape" 
       onClick={() => escapeForm() } 
       > 
       <i className='fa fa-times'></i> 
       </button> 
      </span> 
      { renderCompanyInfo() } 
      <ul className="nav nav-tabs"> 
       <li className="nav-item"> 
       <a href="#" className="nav-link active">Select Existing SKU</a> 
       </li> 
       {/* <li className="nav-item"> 
       <a href="#" className="nav-link">Clone & Edit an Existing Order</a> 
       </li> */} 
      </ul> 
      <Form id="createOrder" onSubmit={ handleSubmit(this.openConfirmationDialog.bind(this))}> 
       <fieldset> 
       <div className="card card-block order-card"> 
        <h3 className="card-title"> 
        </h3> 
        <p className="card-text"> 
        <strong> 
         Select a List, and then a SKU&nbsp; 
        </strong> 
        </p> 
        <div className="form-group"> 
        <div className="form-group row"> 
         <div className="col-md-6"> 
         <div className="form-group"> 
          <Field 
          name="listId" 
          component={ this.renderGenericField } 
          label="List" 
          /> 
         </div> 
         </div> 
         <div className="col-md-6"> 
         <span className="col-sm-10 pull-right"> 
          <button 
          type="button" 
          className="btn btn-secondary btn-back" 
          onClick={ previousPageFunction } 
          > 
          Back 
          </button> 
          <button 
          type="submit" 
          className="btn btn-primary" 
          disabled={ submitting } 
          > 
          Place Order 
          </button> 
         </span> 
         </div> 
        </div> 
        </div> 
       </div> 
       </fieldset> 
      </Form> 
      <PriceBookTableContainer 
       accountId={ accountId } 
       dialog={ dialog } 
       isDAdmin={ false } 
       isCRM={ isCRMTable } 
       isPAdmin={ false } 
       tableContents={ isCRMTable ? priceBook.get('crmList') : priceBook.get('maList') } 
       revShare={ priceBook.get('revShare') } 
       openDialogFunction={() => { 
       } } 
       closeDialogFunction={() => { 
       } } 
       updatePriceAction={() => { 
       } } 
      /> 
      </div> 
     </div> 
     { dialog.id === 'confirmOrderDialog' && dialog.show ? 
      <ConfirmOrderDialog 
      dataSets={ dataSets } 
      dialog={ dialog } 
      formValues={ formValues } 
      fieldSets={ fieldSets } 
      selectedPbData={ selectedPbData } 
      platformMap={ platformMap } 
      useCaseMap={ useCaseMap } 
      closeDialogFunction={ closeDialogFunction } 
      submitOrderFunction={ this.createOrderFunction } 
      /> : null } 
     </div> 
    ); 
    } 

    renderGenericField = ({ input, label, meta: { touched, error } }) => { 
    return (
     <div className={ getClassName(touched, error) }> 
     <label className="form-control-label row"> 
      {label}:&nbsp; 
      { touched && error && <span> | {error} </span> } 
     </label> 
     { this.renderSpecialInput(label, input) } 
     </div> 
    ); 
    } 

    renderSpecialInput = (label, input) => { 
    if (label === 'List') { 
     return this.renderListIdSelect(input); 
    } 
    else if (label === 'SKU') { 
     return this.renderSkuIdSelect(input); 
    } 
    else if (label === 'Start date') { 
     return this.renderDateTimeInput(
     this.handleStartDayChange, 
     ((typeof input === 'string') ? null : input) 
    ); 
    } 
    else if (label === 'End date') { 
     return this.renderDateTimeInput(
     this.handleEndDayChange, 
     ((typeof input === 'string') ? null : input) 
    ); 
    } 
    return null; 
    } 

    renderDateTimeInput = (changeMethod, value) => { 
    const date = new Date(); 
    return (
     <div className="form-group row"> 
     <div className="col-sm-10"> 
      <DateTimePicker 
      time={ false } 
      min={ date } 
      parse={ formats } 
      onChange={ param => changeMethod(param) } 
      value={ value } 
      /> 
     </div> 
     </div> 
    ); 
    } 

    renderListIdSelect = (input) => { 
    const { fetchFieldsetsByIdFunction, dataSets } = this.props; 
    return (
     <select 
     {...input} 
     onChange={(event) => { 
      input.onChange(event); 
      const dataset = JSON.parse(event.target.value); 
      fetchFieldsetsByIdFunction(dataset.id, 
      'SKU', 
      storeWithExpiration.get('token')); 
     }} 
     className="form-control form-control-lg form-control-success" 
     autoFocus 
     > 
     <option value="">&lt; Please Select &gt;</option> 
     { dataSets.size > 0 ? 
      dataSets.valueSeq().map(this.renderDataSetItem) : null } 
     </select> 
    ); 
    } 

    renderSkuIdSelect = (input) => { 
    const { fieldSets } = this.props; 
    return (
     <select 
     {...input} 
     className="form-control form-control-lg form-control-success" 
     value={input || ''} 
     > 
     <option value="">&lt; Please Select &gt;</option> 
     { fieldSets.size > 0 ? 
      fieldSets.valueSeq().map(this.renderItem) 
      : 
      <option value="-1">No SKU's found</option> } 
     </select> 
    ); 
    } 

    renderDataSetItem = (item) => { 
    // Only render lists that are live (pending lists don't have SKUs) 
    if (item.status !== 0) { 
     return this.renderItem(item); 
    } 

    return null; 
    } 

    renderItem = (item) => { 
    return (
     <option key={ item.id } value={ JSON.stringify(item) }>{ item.name }</option> 
    ); 
    } 

    componentWillMount =() => { 
    const { 
     accountId, 
     getRevShareAction, 
     getPriceBookAction } = this.props; 
    let { formValues: { startDay, endDay } } = this.props; 

    const token = storeWithExpiration.get('token'); 

    getPriceBookAction(accountId, token); 
    getRevShareAction(accountId, token); 

    startDay = null; 
    endDay = null; 
    } 
} 

const validate = values => { 
    const isCRM = values.platformCode === 'SFDC'; 
    const today = new Date(moment().set('hour', 0).set('minute', 0).set('second', 0).format()); 
    const onMonthFromNow = new Date(moment(today).add(1, 'M').format()); 
    let oneMonthFromStartDate = onMonthFromNow; 
    if (values.startDay) { 
    oneMonthFromStartDate = new Date(moment(values.startDay).add(1, 'M').format()); 
    } 
    const errors = {}; 
    if (!values.listId || values.listId === '') { 
    errors.listId = 'Required'; 
    } 
    if (!values.skuId || values.skuId === '') { 
    errors.skuId = 'Required'; 
    } 
    else if (values.skuId === '-1') { 
    errors.skuId = 'Please Select a List With a SKU and Try Again'; 
    } 
    // Credits 
    if (!values.recordCredits || values.recordCredits === '') { 
    errors.recordCredits = 'Required'; 
    } 
    else if (isNaN(Number(values.recordCredits))) { 
    errors.recordCredits = 'Must be a number'; 
    } 
    else if (Number(values.recordCredits) < 1) { 
    errors.recordCredits = 'Must be greater than 0'; 
    } 
    else if (parseInt(values.recordCredits, 10) !== Number(values.recordCredits)) { 
    errors.recordCredits = 'Should be an integer'; 
    } 
    // Number of seats 
    // Nested if statements seem to break validate function. Using workaround 
    if (!isCRM) { 
    // Don't validate Number of seats 
    } 
    else if (!values.numberOfSeats || values.numberOfSeats === '') { 
    errors.numberOfSeats = 'Required'; 
    } 
    else if (isNaN(Number(values.numberOfSeats))) { 
    errors.numberOfSeats = 'Must be a number'; 
    } 
    else if (Number(values.numberOfSeats) < 1) { 
    errors.numberOfSeats = 'Must be greater than 0'; 
    } 
    else if (parseInt(values.numberOfSeats, 10) !== Number(values.numberOfSeats)) { 
    errors.numberOfSeats = 'Should be an integer'; 
    } 
    else if (parseInt(values.numberOfSeats, 10) > 1000) { 
    errors.numberOfSeats = 'Please contact Datarista for orders over 1000'; 
    } 
    // Number of records 
    if (isCRM) { 
    // Don't validate Number of records 
    } 
    else if (!isCRM && !values.numberOfRecords || values.numberOfRecords === '') { 
    errors.numberOfRecords = 'Required'; 
    } 
    else if (isNaN(Number(values.numberOfRecords))) { 
    errors.numberOfRecords = 'Must be a number'; 
    } 
    else if (Number(values.numberOfRecords) < 1) { 
    errors.numberOfRecords = 'Must be greater than 0'; 
    } 
    else if (parseInt(values.numberOfRecords, 10) !== Number(values.numberOfRecords)) { 
    errors.numberOfRecords = 'Should be an integer'; 
    } 
    else if (parseInt(values.numberOfRecords, 10) > 50000) { 
    errors.numberOfRecords = 'Please contact Datarista for orders over 50,000k'; 
    } 
    // Start and end times 
    if (values.endDay === null || values.endDay === undefined) { 
    errors.endDay = 'Required'; 
    } 
    else if (values.endDay < onMonthFromNow) { 
    errors.endDay = '1 month Minimum Contract Required'; 
    } 
    else if (values.endDay < oneMonthFromStartDate) { 
    errors.endDay = '1 month Minimum Contract Required'; 
    } 
    if (values.startDay === null || values.startDay === undefined) { 
    errors.startDay = 'Required'; 
    } 
    else if (values.startDay < today) { 
    errors.startDay = 'Start date can\'t be before today'; 
    } 
    else if (values.startDay >= values.endDay) { 
    errors.startDay = 'Must preceed end date'; 
    errors.endDay = 'Must follow start date'; 
    } 
    return errors; 
}; 

function mapStateToProps(state) { 
    const { account, priceBook } = state; 
    const accountId = account.id; 

    return { accountId, priceBook }; 
} 

NewOrderFormFour = reduxForm({ 
    form: 'createOrder', 
    destroyOnUnmount: false, 
    validate, 
}); 

export default connect(mapStateToProps, { 
    getRevShareAction: getRevShare, 
    getPriceBookAction: getPriceBook, 
})(NewOrderFormFour); 

答えて

2

は、ここで全体の構成要素です。これに代えて

NewOrderFormFour = reduxForm({ 
    form: 'createOrder', 
    destroyOnUnmount: false, 
    validate, 
})(NewOrderFormFour); 

を:: reduxFormは、あなたがこのようsomethigを使用しなければならないので、と呼ばれる引数としての成分を反応させるべきであるデコレータ関数を作成し

+0

おかげでそんなに...私は忘れて知っていた

NewOrderFormFour = reduxForm({ form: 'createOrder', destroyOnUnmount: false, validate, }); 
何か。私はすでにそれをしていたと思っていますが、私はそれを逃してしまったに違いないと誓っています。再度、感謝します。 –

+0

あなたを歓迎します。私はあなたを助けることができてうれしいよ:) –

関連する問題