Redux表单不会重置

时间:2016-12-16 22:01:49

标签: reactjs redux redux-form

我有一个基于道具的组件呈现具有不同组件的表单。

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组件收到新的道具并且表格更新时。当新道具的表单组件与旧道具的表单组件相同时,旧值仍保持选中状态。

当新道具的表单组件不同时,并未按预期选择所有值,但我可以在不选择任何内容的情况下提交表单,这应该通过验证来阻止。

我希望你有任何建议,我现在完全没有想法。

3 个答案:

答案 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', {}));
        }
      }
    );