Reactjs + Redux Form FieldArray условного рендеринга - PullRequest
0 голосов
/ 21 ноября 2018

Я новичок в ReactJS и Redux.Я пытаюсь получить сложную динамическую форму, используя реактив и редукс-форму.Короткая история:

Мне нужно динамически генерировать формы, которые позволяют множественные ответы, имеющие несколько типов.Больше или меньше, как работают формы Google.

Обычно пользователь может создать свою собственную форму / анкету.Пример:

Вы когда-нибудь были в Нью-Йорке?(радио -> Да / Сейчас)

Если пользователь нажимает Да, задайте другой набор вопросов:

Сколько времени вы потратили на посещение?(флажок: 1-2 часа, 2-4 часа, 4-6 часов)

Если пользователь нажимает на "4-6 часов", задайте еще один вопрос:

Вау!Можете ли вы сказать нам, где именно вы проводите столько времени?(текстовый ответ)

И так далее.Конечно, это только базовый пример, формы были бы еще более сложными, чем эта.

Теперь перейдем к коду.Мой первоначальный подход состоял в том, чтобы использовать FieldArray.Вот как это выглядит:

  <FieldArray 
    name="question" 
    component={renderMultipleCheckboxes} 
    options={[{id:1,value:true,label:'a'},{id:2,value:true,label:'b'}]}
    allowAnswer={true}
    allowAnswerForValue={[2]}
    allowAnswerFieldName="question_answer"
    allowAnswerFieldLabel="Your answer"
  />

Этот FieldArray является частью большой формы, экспортируемой как:

Form.propTypes = {
  user: PropTypes.object.isRequired
}

Form = reduxForm({
  form: 'form_x',
})(Form);

Form = connect(state => ({
  account: state.account,
}))(Form);

export default Form;

renderMultipleCheckboxes:

export class renderMultipleCheckboxes extends React.PureComponent {

  render() {
    const {   
      input,
      fields, 
      options, 
      meta: { error, submitFailed }, 
      allowAnswer,
      allowAnswerForValue,
      allowAnswerFieldName,
      allowAnswerFieldLabel 
    } = this.props;

    return fields.map((item, index) => { 

      let option = options.map((item) => {
        if (item.id === index) {
          return item;
        }
      })

      // What would be the approach to show answer input ? This line of code works only once.  
      let showAnswerField = document.getElementsByName(item)[0].checked && allowAnswer && allowAnswerForValue.indexOf(index) > -1;

      return (
        <React.Fragment>
          <Field
            label={option[index].label}
            name={`${item}`}
            component={renderCheckBoxField}
            key={index}
          />
          {showAnswerField &&
            <Field
              label={allowAnswerFieldLabel}
              name={allowAnswerFieldName}
              component={'input'}
              key={index + 1}
            />
          }
        </React.Fragment>
      )
    })
  }
}

renderCheckBoxField:

class CheckBoxField extends PureComponent {
  componentDidMount() {
    this.props.onChange(this.props.defaultChecked);
  }

  render() {
    const disabled = this.props.disabled;

    return (
      <label
        className={`checkbox-btn${disabled ? ' disabled' : ''}${this.props.class ? ` checkbox-btn--${this.props.class}` : ''}`}>
        <input className='checkbox-btn__checkbox'
               type='checkbox' name={this.props.name} onChange={this.props.onChange}
               checked={this.props.value} disabled={disabled}/>
        <span className='checkbox-btn__checkbox-custom'
              style={this.props.color ? {background: this.props.color, borderColor: this.props.color} : {}}>
            <CheckIcon/>
          </span>
        {this.props.class === 'button' ?
          <span className='checkbox-btn__label-svg'>
              <CheckIcon className='checkbox-btn__label-check'/>
              <CloseIcon className='checkbox-btn__label-uncheck'/>
            </span> : ''}
        <span className='checkbox-btn__label'>
          {this.props.label}
          </span>
      </label>
    )
  }
}

const renderCheckBoxField = (props) => {
  let label = props.label;
  return (
  <CheckBoxField
    {...props.input}
    label={label}
    defaultChecked={props.defaultChecked}
    disabled={props.disabled}
    class={props.class}
    color={props.color}
  />
)};

renderCheckBoxField.propTypes = {
  input: PropTypes.object.isRequired,
  label: PropTypes.string,
  defaultChecked: PropTypes.bool,
  disabled: PropTypes.bool,
  class: PropTypes.string,
  color: PropTypes.string
};

export default renderCheckBoxField;

Я не уверен, объяснил ли я себя достаточно хорошо.

ВАЖНО: я не могу использовать formValues, потому что поля формы генерируются динамически.Или, по крайней мере, я не знаю, как этого добиться.

...