我正在尝试使用高阶组件(HOC)模式来重用一些连接到状态的代码,并使用Redux Form formValueSelector方法。
formValueSelector需要一个引用表单名称的字符串。我想动态地设置这个,并且能够在我需要项目的值时使用这个HOC。我使用项目值进行计算。
在下面的代码中,向HOC传递组件和字符串。我想把它设置为从父类(表单)传入的prop formName。
我是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: use ownProps
parameter
你应该做的草稿
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
。
这是它的签名:
mapStateToProps(state, [ownProps]): stateProps
我要说明的是ownProps
参数。
ownProps
包含所有传递给连接组件的道具。
澄清一下,你有这些组件
- 常规组件:即
StatementLineItemDesktop
和Base
- 已连接组件:即
ConnectedBase = connect(mapStateToProps)(Base)
因此,根据这些信息,称为FormItemsValueSelectorHOC
的HOC函数返回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
源代码,它不长也不困难,所以你可能可以探索和理解这个答案的更多内容。
希望这对你有帮助。