我正在尝试使用高阶组件(HOC)模式来重用一些连接到状态并使用Redux Form formValueSelector方法的代码。
formValueSelector需要一个字符串来引用表单的名称。我想动态设置它,并在需要项目值时能够使用此HOC。我使用项目值进行计算。
在HOC下面的代码中传递了组件和字符串。我想将其设置为从parent(form)传入的prop 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');
TLDR:使用ownProps参数
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;
这将是您创建连接组件的方式
formItemsValueSelectorHOC(StatementLineItemDesktop);
这就是您使用它的方式
<ConnectedStatementLineItemDesktop formName={"editQuote"} />
让我再解释一下这是如何工作的
您所缺少的是React-Redux API,您可能应该对其进行更多的研究,因为它已经考虑了很多这种用例
因此,React-Redux connect函数的第一个参数称为mapStateToProps。
connect
mapStateToProps
这是它的签名:
mapStateToProps(state, [ownProps]): stateProps
我要说明的是ownProps参数。
ownProps 包含所有传递给所连接组件的道具。
为了澄清起见,您具有以下组件
StatementLineItemDesktop
Base
ConnectedBase = connect(mapStateToProps)(Base)
因此,根据此信息,您的HOC函数调用FormItemsValueSelectorHOC返回的变体ConnectedBase。
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,因此从逻辑上考虑,您使用普通组件执行的大多数操作也将可以使用连接的Components完成,我建议您阅读connect源代码,时间不长也不困难,因此您可能可以探索和理解更多答案。
希望对您有所帮助。