我正在使用React Redux,Redux-form并重新选择库(https://github.com/reactjs/reselect)。
我有一个包含两个字段的组件:id sequence card_tap time
1 1 61 1
1 1 62 10
2 12 62 10
2 12 61 20
和quota
。我想根据amount
字段更新amount
字段。对于quota
的计算,我使用amount
和selector
。
我希望仅在有效reselect
时更新amount
字段。
我试过没有成功的quota
字段道具,因为它是在选择器之前执行的。
我发现的最佳解决方案是使用onChange
reduxForm()属性,因为它在选择器之后执行但我在验证后无法运行。
这是我的代码:
onChange
答案 0 :(得分:2)
答案是使用formValueSelector
并在componentWillReceiveProps
(或componentDidUpdate
)中更新。以下是工作Modal.js
的版本。请注意,quota
验证在验证函数和计算中都会重复使用。
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Field, reduxForm, formValueSelector } from 'redux-form'
const validateQuota = quota => {
if (quota <= 1) {
return 'The quota must be greater than 1'
} else if (quota > 50) {
return 'The quota must be less than 50'
}
}
const validate = values => {
const errors = {}
errors.quota = validateQuota(values.quota)
return errors
}
/**
* Arbitrary function that takes quota and calcuates amount.
* For the purposes of this demo, I'm assuming that we're a
* mobile phone company and are charging $19.95 per 5 GB of quota.
*/
const calculateAmount = quota => Math.ceil(quota / 5) * 19.95
class Modal extends Component {
renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
)
componentWillReceiveProps(nextProps) {
const { change, quota } = nextProps
if (this.props.quota !== nextProps.quota && !validateQuota(quota)) {
// quota value is valid
change('amount', calculateAmount(quota))
}
}
render() {
return (
<div>
<label>Quota</label>
<Field
name="quota"
component={this.renderField}
type="number"
label="Quota"
/>
<label>Amount</label>
<Field
name="amount"
component={this.renderField}
type="number"
label="Amount"
/>
</div>
)
}
}
const valueSelector = formValueSelector('modal') // <-- form name
const makeMapStateToProps = () => {
const mapStateToProps = state => {
return {
quota: valueSelector(state, 'quota'),
initialValues: {
// Not implementing the modal reducer...
// quota: state.modal.quota,
// amount: state.modal.amount
}
}
}
return mapStateToProps
}
Modal = reduxForm(
{
form: 'modal',
enableReinitialize: true,
validate
},
makeMapStateToProps
)(Modal)
const mapDispatchToProps = undefined // not included in StackOverflow snippet
Modal = connect(makeMapStateToProps, mapDispatchToProps)(Modal)
export default Modal