2016-10-06 43 views
3

我试图使用高阶组件(HOC)模式来重新使用一些连接到状态并使用Redux Form的formValueSelector方法的代码。在调用高阶组件时,在React的类的外部访问道具

formValueSelector需要一个引用表单名称的sting。我想动态地设置它,并且只要我需要项目的值就能够使用这个HOC。我使用项目值进行计算。

在下面的代码中,HOC传递组件和一个字符串。我想将其设置为已从父(形式)传入的道具formName。

我是新来的HOC模式,所以任何提示将不胜感激。

HOC

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 
import { formValueSelector } from 'redux-form'; 

function FormItemsValueSelectorHOC(FormElement, formName) { 
    const selector = formValueSelector(formName); 
    @connect(state => { 
    console.log(state); 
    const items = selector(state, 'items'); 
    return { 
     items 
    }; 
    }, null) 
    class Base extends Component { 
    render() { 
     return (
     <FormElement {...this.props} /> 
    ); 
    } 
    } 
    return Base; 
} 
export default FormItemsValueSelectorHOC; 

裹组件

import React, { Component, PropTypes } from 'react'; 
import { Field } from 'redux-form'; 
import formItemsValueSelectorHOC from '../Utilities/FormItemsValueSelectorHOC'; 

const renderField = ({ placeholder, input, type}) => { 
    return (
    <input 
     {...input} 
     placeholder={placeholder} 
     type={type} 
    /> 
); 
}; 

class StatementLineItemDesktop extends Component { 
    static propTypes = { 
    items: PropTypes.array.isRequired, 
    index: PropTypes.number.isRequired, 
    item: PropTypes.string.isRequired, 
    fields: PropTypes.object.isRequired, 
    formName: PropTypes.string.isRequired 
    }; 

    calculateLineTotal(items, index) { 
    let unitPrice = '0'; 
    let quantity = '0'; 
    let lineTotal = '0.00'; 
    if (items) { 
     if (items[index].price) { 
     unitPrice = items[index].price.amountInCents; 
     } 
     quantity = items[index].quantity; 
    } 
    if (unitPrice && quantity) { 
     lineTotal = unitPrice * quantity; 
     lineTotal = Number(Math.round(lineTotal+'e2')+'e-2').toFixed(2); 
    } 
    return <input value={lineTotal} readOnly placeholder="0.00" />; 
    } 

    render() { 
    const { items, index, item, fields, formName} = this.props; 
    return (
     <tr id={`item-row-${index}`} key={index} className="desktop-only"> 
     <td> 
      <Field 
      name={`${item}.text`} 
      type="text" 
      component={renderField} 
      placeholder="Description" 
      /> 
     </td> 
     <td> 
      <Field 
      name={`${item}.quantity`} 
      type="text" 
      component={renderField} 
      placeholder="0.00" 
      /> 
     </td> 
     <td> 
      <Field 
      name={`${item}.price.amountInCents`} 
      type="text" 
      component={renderField} 
      placeholder="0.00" 
      /> 
     </td> 
     <td className="last-col"> 
      <Field 
      name={`${item}.price.taxInclusive`} 
      type="hidden" 
      component="input" 
      /> 
      {::this.calculateLineTotal(items, index)} 
      <a 
      className="remove-icon" 
      onClick={() => fields.remove(index)} 
      > 
      <span className="icon icon-bridge_close" /> 
      </a> 
     </td> 
     </tr> 
    ); 
    } 
} 

export default formItemsValueSelectorHOC(StatementLineItemDesktop, 'editQuote'); 
+0

不知道这对我来说是否清楚,但是您是否想过只导出响应组件'StatementLineItemsDesktop'类,并将此React组件与formItemsValueSelectorHOC'函数一起导入声明父组件的文件中,以便您可以调用这个HOC在你父母的'render()'方法中使用'this.props.formName'作为第二个参数? – dzv3

回答

4

TLDR:使用ownProps参数

的你应该做的

import React, { Component } from 'react'; 
import { connect } from 'react-redux'; 
import { formValueSelector } from 'redux-form'; 

function FormItemsValueSelectorHOC(FormElement) { 
    @connect((state, ownProps) => { 
    const formName = ownProps.formName; 
    const selector = formValueSelector(formName); 
    const items = selector(state, 'items'); 
    return { 
     items 
    }; 
    }, null) 
    class Base extends Component { 
    render() { 
     // Now in here you should omit `formName` from the props you are 
     // passing to your Form Element since it's not used overthere 
     return (
     <FormElement {...this.props} /> 
    ); 
    } 
    } 
    return Base; 
} 
export default FormItemsValueSelectorHOC; 

草案,该W生病是您将创建连接组件

formItemsValueSelectorHOC(StatementLineItemDesktop); 

的方式,这将是你使用它的方式

<ConnectedStatementLineItemDesktop formName={"editQuote"} /> 

让我解释一点这项工作如何

的事情,你缺少的是React-Redux API,您应该更多地探索它,因为它已经考虑了很多这种使用案例

因此,React-Redux的connect func重刑的第一个参数叫做mapStateToProps

这是它的签名:

mapStateToProps(state, [ownProps]): stateProps 

,我想谈谈的事情是ownProps参数。

ownProps包含传递给连接组件的所有道具。

只是为了澄清,你有这些成分

  • 常规组件:即StatementLineItemDesktopBase
  • 连接的设备:即ConnectedBase = connect(mapStateToProps)(Base)

所以,从这个信息,您的HOC函数调用FormItemsValueSelectorHOC返回ConnectedBase的变体。

所以,你传递给ConnectedBase或任何部分它是从FormItemsValueSelectorHOC返回你可以从ownProps

访问他们顺便说一句,你的具体情况的任何道具,这是你的mapStateToProps

function mapStateToProps(state, ownProps) { 
    const formName = ownProps.formName; 
    const selector = formValueSelector(formName); 
    const items = selector(state, 'items'); 
    return { 
    items 
    }; 
} 

的事需要注意的是,connect也是一个HOC,所以从逻辑上来说,你认为你使用普通组件做的大部分事情都可以用连接组件完成,我建议你阅读connect源代码, DIF很难,所以你可以探索和理解更多的这个答案。

我希望这有助于。

+0

很好回答! –

相关问题