簡體   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