2016-12-16 54 views
0

我有一个基于道具的组件可以渲染一个带有不同组件的窗体。Redux窗体不会重置

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

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

我希望你有任何建议,我完全没有想法在这一点上。

+1

如果您设置一个可以复制问题的小工具,您将收到更有可能的答案。我已经在webpackbin中为你设置了所有的样板文件,所以在那里重现你的问题。或者使用您选择的任何其他提琴手。我的样板位于http://www.webpackbin.com/NJ2Nd-0QG请注意,保存更改后网址会发生变化,因此请包含更新后的网址。 – Anarion

+1

感谢您的回复。我现在感到有点愚蠢,这从来没有发生过我。由于某种原因,这个问题在向我的项目中添加material-ui后神奇地解决了。但我下次肯定会这样做。感谢您的建议! – Rothkrebschen

回答

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 
    } 
} 
1

最好的方法,我发现:

进口“初始化” ......

import {initialize} from 'redux-form'; 

,然后当你打电话的动作,传递一个空对象到之后调用另一个动作'初始化'功能...

yourFunction = (data) => { 
    this.props.dispatch(yourAction(data)) 
    .then(
     result => { 
     if (result) { 
      this.props.dispatch(initialize('nameOfTheForm', {})); 
     } 
     } 
    );