我有一个基于道具的组件呈现具有不同组件的表单。
class Feedback extends Component {
submitMyForm(data) {
const { onSubmit, reset } = this.props;
reset();
return onSubmit(data);
//
// do other success stuff
}
render() {
const { handleSubmit } = this.props;
let component;
if(this.props.data.feedbackType == "likert")
component = Likert;
else if(this.props.data.feedbackType == "single choice")
component = SingleChoice;
else if(this.props.data.feedbackType == "multiple choice")
component = MultipleChoice;
return (
<div>
<h1>Feedback zu Aufgabe {this.props.id}</h1>
<form onSubmit={handleSubmit(this.submitMyForm.bind(this))}>
<Field
name="feedback"
component={component}
heading={this.props.data.description}
items={this.props.data.options}
required={true}
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
}
// Decorate the form component
Feedback = reduxForm({
form: 'feedback', // a unique name for this form,
validate,
enableReinitialize:true
})(Feedback);
function validate(formProps) {
const errors = {};
if (!formProps.feedback) {
errors.feedback = 'please select an option';
}
return errors;
}
export default Feedback;
import React, { PropTypes } from 'react';
const SingleChoice = ({ input, disabled, heading, required, className, items, name, meta: { touched, error } }) => (
<fieldset className={`form__field ${className || ''}`}>
<legend className="form__label">
{heading}{required ? (<span>*</span>) : null}
{ (touched && error) ? (
<span className="form__error"> {error}</span>
) : null }
</legend>
<div>
{ items.map((item, i) => (
<div className="form__segmented-control width-1/2@small" key={ i }>
<input
{...input}
name={ name }
type="radio"
value={ item.value }
disabled={ disabled }
className="segmented-control__input u-option-bg-current"
id={ `${name}-${item.value}` }
/>
<label className="segmented-control__label u-adjacent-current" htmlFor={ `${name}-${item.value}` }>
{item.label}
</label>
</div>
))
}
</div>
</fieldset>
);
SingleChoice.propTypes = {
input: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
className: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string.isRequired,
value: PropTypes.any.isRequired,
})).isRequired,
heading: PropTypes.string,
meta: PropTypes.object,
required: PropTypes.bool,
disabled: PropTypes.bool,
};
export default SingleChoice;
第一次表单渲染一切都很好。所有单选按钮都是未选中的,如果我尝试提交它,我会收到预期的验证错误。但是当我的Feeback组件收到新的道具并且表格更新时。当新道具的表单组件与旧道具的表单组件相同时,旧值仍保持选中状态。
当新道具的表单组件不同时,并未按预期选择所有值,但我可以在不选择任何内容的情况下提交表单,这应该通过验证来阻止。
我希望你有任何建议,我现在完全没有想法。
答案 0 :(得分:2)
我搜索了数小时,试图找到解决该问题的方法。我可以解决的最佳方法是使用plugin()API来指导redux-formreduce响应提交成功后分派的操作。就像这里的第一步How can I clear my form after my submission succeeds?
const reducers = {
// ... your other reducers here ...
form: formReducer.plugin({
nameOfTheForm: (state, action) => { // <- 'nameOfTheForm' is name of form
switch(action.type) {
case ACCOUNT_SAVE_SUCCESS:
const values = undefined;
const fields = {
fields: {
input_field_name: {
visited: false,
touched: false
}
// repeat for each input field
}
};
const newState = { ...state, values, fields };
return newState;
default:
return state;
}
}
})
}
您将不得不在组件中进行一些更改。
onSubmit(values) {
this.props.postForm(values, () => {});
}
render(){
const { handleSubmit } = this.props;
}
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}></form>
)
在您的操作文件中:
export function postForm(values, callback) {
const request = axios.get(`${ROOT_URL}`, config).then(() => callback());
return {
type: ACCOUNT_SAVE_SUCCESS,
payload: request
};
}
答案 1 :(得分:1)
当我的Feeback组件收到新道具并且表单更新时,当新道具的表单组件与旧道具的表单组件相同时,旧值仍保持选中状态。
这是因为feedback
表单的值存储在Redux商店中
您应该实施componentWillReceiveProps
并测试您的表单是否应该重置。
class Feedback extends Component {
componentWillReceiveProps ( nextProps ) {
if ( nextProps.blabla !== this.props.blabla ) {
// oh cool, props changed, let's reset the form
// checkout more available form props at http://redux-form.com/6.4.3/docs/api/ReduxForm.md/
this.props.reset();
}
}
render () {
// your normal rendering function
}
}
答案 2 :(得分:1)
我找到的最佳方式:
导入&#39;初始化&#39; ...
import {initialize} from 'redux-form';
然后当你调用动作时,在将空对象传递给&#39;初始化&#39;之后立即调用另一个动作。功能...
yourFunction = (data) => {
this.props.dispatch(yourAction(data))
.then(
result => {
if (result) {
this.props.dispatch(initialize('nameOfTheForm', {}));
}
}
);