admin管理员组文章数量:1313082
I am trying to use a Higher Order Component(HOC) pattern to reuse some code that connects to state and uses the Redux Form formValueSelector method.
formValueSelector requires a sting referencing the name of the form. I would like to set this dynamically and be able to use this HOC whenever I need the values of items. I use the item values to make calculations.
In the code below the HOC is passed the ponent and a string. I would like to set this to the prop formName that has been passed in from the parent(form).
I am new to the HOC pattern so any tips would be most appreciated.
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;
Wrapped Component
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"
ponent={renderField}
placeholder="Description"
/>
</td>
<td>
<Field
name={`${item}.quantity`}
type="text"
ponent={renderField}
placeholder="0.00"
/>
</td>
<td>
<Field
name={`${item}.price.amountInCents`}
type="text"
ponent={renderField}
placeholder="0.00"
/>
</td>
<td className="last-col">
<Field
name={`${item}.price.taxInclusive`}
type="hidden"
ponent="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');
I am trying to use a Higher Order Component(HOC) pattern to reuse some code that connects to state and uses the Redux Form formValueSelector method.
formValueSelector requires a sting referencing the name of the form. I would like to set this dynamically and be able to use this HOC whenever I need the values of items. I use the item values to make calculations.
In the code below the HOC is passed the ponent and a string. I would like to set this to the prop formName that has been passed in from the parent(form).
I am new to the HOC pattern so any tips would be most appreciated.
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;
Wrapped Component
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"
ponent={renderField}
placeholder="Description"
/>
</td>
<td>
<Field
name={`${item}.quantity`}
type="text"
ponent={renderField}
placeholder="0.00"
/>
</td>
<td>
<Field
name={`${item}.price.amountInCents`}
type="text"
ponent={renderField}
placeholder="0.00"
/>
</td>
<td className="last-col">
<Field
name={`${item}.price.taxInclusive`}
type="hidden"
ponent="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');
Share
Improve this question
edited Oct 6, 2016 at 1:43
m0meni
16.5k18 gold badges87 silver badges148 bronze badges
asked Oct 6, 2016 at 1:39
Dom HedeDom Hede
1,0669 silver badges19 bronze badges
1
-
Not sure if it's clear to me, but have you thought of exporting just the react ponent
StatementLineItemsDesktop
class and importing this React ponent along with theformItemsValueSelectorHOC
function in the file where your parent ponent is declared so you can call this HOC in your parent'srender()
method usingthis.props.formName
as the 2nd argument? – Diego Zacarias Commented Oct 6, 2016 at 6:29
1 Answer
Reset to default 6TLDR: use ownProps
parameter
Draft of what you should do
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;
And this will be the way you will create your connected ponent
formItemsValueSelectorHOC(StatementLineItemDesktop);
And this will be the way you use it
<ConnectedStatementLineItemDesktop formName={"editQuote"} />
Let me explain a bit more how this work
The thing that you were missing is React-Redux API, you should probably explore it more because it already contemplates a lot of this use cases
So, React-Redux's connect
function's first parameter is called mapStateToProps
.
This is its signature:
mapStateToProps(state, [ownProps]): stateProps
The thing that I want to remark is the ownProps
parameter.
ownProps
contains all the props that are passed to your connected ponent.
Just for clarification, you have these ponents
- Regular Component: i.e.
StatementLineItemDesktop
andBase
- Connected Component: i.e.
ConnectedBase = connect(mapStateToProps)(Base)
So, from this information, your HOC function called FormItemsValueSelectorHOC
returns a variation of ConnectedBase
.
So, whatever props you pass to ConnectedBase
or whatever ponent it's returned from FormItemsValueSelectorHOC
you can access them from ownProps
BTW, in your particular case, this is your mapStateToProps
function mapStateToProps(state, ownProps) {
const formName = ownProps.formName;
const selector = formValueSelector(formName);
const items = selector(state, 'items');
return {
items
};
}
The thing to Note is that connect
is also an HOC, so it's logically to think that most of the things you do with normal ponents you will also be able to do with connected Components, I would suggest for you to read the connect
source, it's not long nor difficult so you can probably explore and prehend more of this answer.
I hope this helped.
本文标签: javascriptAccess prop outside of class in React when calling Higher Order ComponentStack Overflow
版权声明:本文标题:javascript - Access prop outside of class in React when calling Higher Order Component - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741930023a2405519.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论