繁体   English   中英

如何将道具传递到“ redux-form”中的装饰形式?

[英]How to pass down props to decorated form in `redux-form`?

我正在使用redux-form构建向导表单,并遇到一个问题,其中onClick处理程序没有作为prop从容器组件传递到表单中。

我已经搜索了过去几个小时的文档,但无济于事……似乎有一种方法可以将道具传递到装饰好的HOC中,但是我看不到任何此类示例。

以下是相关代码:

RadioButtons.js (在其中调用onClick函数)

const RadioButtons = props => {
  const { question, handleClick } = props;
  const radioClassNames = classNames({
    "radio-button": true,
    "radio-button-image-wrapper": question.image,
    "radio-button-text-wrapper": !question.image,
  });
  return (
    <div className="radio-buttons">
      <div className="radio-buttons-wrapper">
        {question.options.map((option, index) => (
          <div className={radioClassNames} key={index} onClick={handleClick}>
            <Field
              component="input"
              type="radio"
              name={`option-${option}`}
              id={`option-${option}`}
            />
            <label className="radio-button-text" htmlFor={option}>
              {option}
            </label>
        )}
          </div>
        )
        )}
      </div>
    </div>
  )
}

RadioButtons.PropTypes = {
  question: PropTypes.object.isRequired,
  handleClick: PropTypes.func,
}

export default RadioButtons;

当我在React DevTools中检查这个组件时,它没有这个道具。 以下组件中也没有...

Question.js (确定要呈现的问题类型;滑块,单选按钮,文本/电子邮件/电话输入等)

const Question = props => {
  const { handleSubmit, onBlur, question, handleClick } = props;
  return (
    <div className={`question question-${question.name}`}>
      <form className={props.className} onSubmit={handleSubmit}>
        <div className="question-wrapper">
          <label className={`question-label-${question.name}`}>{question.text}</label>
          { question.image === true && question.type !== "checkbox" && question.type !== "radio" &&
            <img className="question-image" src={`/images/${question.name}.png`} />
          }
          { question.type === "radio" && <RadioButtons question={question} handleClick={handleClick} /> }
          { question.type === "range" && <Slider question={question} /> }
          { question.type !== "checkbox" && question.type !== "radio" && question.type !== "range" &&
            <Field
              component={question.component}
              type={question.type}
              name={question.name}
              placeholder={question.placeholder}
              onBlur={onBlur}
            />
          }
        </div>
      </form>
    </div>
  )
}

Question.PropTypes = {
  handleSubmit: PropTypes.func,
  onBlur: PropTypes.func,
  question: PropTypes.object.isRequired,
  handleClick: PropTypes.func,
}

export default reduxForm({
  form: 'quiz',
  destroyOnUnmount: false,
  forceUnregisterOnUnmount: true,
})(Question);

QuestionContainer.js (包装器Question.js ;确定是否呈现在屏幕上或只是一个在多个问题)。 handleClick道具终于出现在这里!

const QuestionContainer = props => {
  const { question, handleClick } = props;

  const questionClassNames = classNames({
    'question-wrapper': true,
    'question-single': props.question !== 'combined',
    'question-multiple': props.question === 'combined',
  });

  const renderQuestions = question => {
    if (question.component === 'combined') {
      return (
       <div className="multi-question-container">
         <label className="multi-question-label">{question.text}</label>
         <div className="multi-question-wrapper">
           {question.subQuestions.map((subQuestion, index) => {
             const newName = `${question.name}-${subQuestion.name}`;
             const newSubQuestion = Object.assign({}, subQuestion, { name: newName })
             return (
               <Question
                 question={newSubQuestion}
                 key={index}
                 className={questionClassNames}
                 handleClick={handleClick}
               />
             )
           })}
         </div>
       </div>
      )} else {
       return (
         <Question
           question={question}
           className={questionClassNames}
         />
       )
     }
  }

  return (
    <div className="question-container">
      {renderQuestions(question)}
    </div>
  )
}

QuestionContainer.PropTypes = {
  question: PropTypes.object.isRequired,
  handleClick: PropTypes.func,
}

export default QuestionContainer;

但是然后... handleClick道具没有显示Quiz组件中,我实际上需要使用它来调用nextScreen()

class Quiz extends Component {
  constructor(props) {
    super(props);
    this.state = {
      screen: 0
    }
  }

  nextScreen = () => {
    console.log("nextScreen");
    if (this.state.screen < data.questions.length) {
      this.setState({screen: this.state.screen + 1});
    } else {
      this.props.calculateResult(this.props.form.quiz.values);
      this.props.history.push('/congratulations');
    }
  }

  lastScreen = () => {
    if (this.state.screen > 1) {
      this.setState({screen: this.state.screen - 1});
    } else {
      this.props.history.push('/');
    }
  }

  render() {

    const currentQuestion = Object.assign({}, data.questions[this.state.screen]);

    let arrowSource = `/images/arrow-button-${arrowColor}.png`;

    return (
      <div>
        <div className="quiz-wrapper">
          <ArrowButton src={arrowSource} route="back" handleClick={this.lastScreen} />
          <div className="quiz-wrapper-inner">
            <QuestionContainer question={currentQuestion} handleClick={this.nextScreen} />
          </div>
          <ArrowButton src={arrowSource} route="forward" handleClick={this.nextScreen} />
        </div>
      </div>
    )
  }
}

const mapStateToProps = state => {
  return {
    form: state.form,
  }
};

const mapDispatchToProps = dispatch => {
  return {
    calculateResult: answers => dispatch(calculateResult(answers)),
  }
};

export default connect(mapStateToProps, mapDispatchToProps)(Quiz);

ArrowButton组件上的handleClick道具工作正常,可以nextScreen()调用nextScreen() / lastScreen() 它只是在QuestionContainer中没有传递下来。

你有两个实例Questions组件的QuestionsContainer组件。 满足question.component === 'combined'条件时,您正在传递handleClick道具,但没有通过,因此在您的Questions组件中不可用。

您还需要在else条件下传递handleClick作为道具

const renderQuestions = question => {
    if (question.component === 'combined') {
      return (
       <div className="multi-question-container">
         <label className="multi-question-label">{question.text}</label>
         <div className="multi-question-wrapper">
           {question.subQuestions.map((subQuestion, index) => {
             const newName = `${question.name}-${subQuestion.name}`;
             const newSubQuestion = Object.assign({}, subQuestion, { name: newName })
             return (
               <Question
                 question={newSubQuestion}
                 key={index}
                 className={questionClassNames}
                 handleClick={handleClick}
               />
             )
           })}
         </div>
       </div>
      )} else {
       return (
         <Question
           question={question}
           className={questionClassNames}
           handleClick={handleClick}
         />
       )
     }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM