如何使用React和Redux Form创建bootstrap切换按钮?

时间:2017-08-22 17:18:04

标签: reactjs react-redux redux-form

我正在尝试使用React,Redux Form和Bootstrap(reactstrap)创建一个可切换的按钮组。

我所做的已经正确更新了redux表单数据。

问题在于按钮颜色属性应该在"成功"之间切换。和"中学"。现在它确实在第一个切换上设置了颜色,但是在我之后点击另一个按钮时不会更新。

这是我的渲染组件:



import React from 'react';
import classNames from 'classnames';
import { Label, FormGroup, ButtonGroup, Button } from 'reactstrap';
import FontAwesome from 'react-fontawesome';

export default class buttonOptions extends React.PureComponent {
  static propTypes = {
    input: React.PropTypes.object,
    buttons: React.PropTypes.any,
    label: React.PropTypes.string,
    meta: React.PropTypes.shape({
      touched: React.PropTypes.bool,
      error: React.PropTypes.any,
    })
  };

  constructor(props) {
    super(props);
    this.toggleOption = this.toggleOption.bind(this);
  }

  toggleOption(val) {
    if (!this.props.input.value.length) this.props.input.value = [];
    // option per buttongroud is always limited to 1
    // remove previously selected options
    for (let b of this.props.buttons) {
      if (b.value !== val && this.props.input.value.indexOf(b.value) > -1) {
        this.props.input.value.splice(this.props.input.value.indexOf(b.value), 1)
      }
    }
    // push the new option and update state
    this.props.input.value.push(val);
    this.props.input.onChange(this.props.input.value)
  }

  render() {
    const { input, buttons, label, meta: { touched, error }} = this.props;
    const labelStyles = {width: '100%', marginBottom: '0'};
    return (
      <FormGroup>
        <Label style={labelStyles}>{label}</Label>
        <ButtonGroup>
          {
            buttons.map((b) => {
              return (
                <Button
                  key={b.title}
                  color={classNames({
                    success: input.value.indexOf(b.value) > -1,
                    secondary: input.value.indexOf(b.value) === -1,
                  })}
                  role="button"
                  onClick={() => { this.toggleOption(b.value) }}
                >
                  {b.title}
                </Button>
              )
            })
          }
        </ButtonGroup>
      </FormGroup>
    );
  }
}
&#13;
&#13;
&#13;

这就是它的实施方式:

&#13;
&#13;
import React from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './AdWizard.css';
import cx from 'classnames';
import FontAwesome from 'react-fontawesome';
import { Field, reduxForm } from 'redux-form'
import { Row, Col, FormGroup, Label, Button } from 'reactstrap';
import buttonOptions from '../FormComponents/buttonOptions';


class Step2 extends React.Component {
  constructor(props) {
    super(props);

    this.workingtimes = [
      {
        title: "Vollzeit",
        value: "Vollzeit",
        selected: true
      },
      {
        title: "Teilzeit",
        value: "Teilzeit",
        selected: false
      }
    ]
  }

  render() {
    const { handleSubmit, previousPage } = this.props;

    return (
      <form onSubmit={handleSubmit}>
        <Row className="justify-content-center">
          <Col xs="12" sm="6">
            <Field
              label="Arbeitszeit"
              name="arbeitszeit"
              buttons={this.workingtimes}
              component={buttonOptions}
            />
          </Col>
        </Row>
      </form>
    )
  }
}

Step2 = reduxForm({
  form: 'posting',
  destroyOnUnmount: false,
  forceUnregisterOnUnmount: true
})(Step2);

export default withStyles(s)(Step2);
&#13;
&#13;
&#13;

如果有人可以提供帮助,那会很棒!

干杯 斯蒂芬

1 个答案:

答案 0 :(得分:0)

您遇到的问题是您的toggleOption功能不纯* 这意味着它正在改变this.props.input.value,而不是创建一个值基于它的新数组 - 简单来说,总是创建一个新的引用!

由于大多数React代码都对纯函数调用非常敏感,所以 你必须将该函数转换为纯函数,以便redux-form实际上看到你改变了数组:

  toggleOption (b) {
    let newValue;
    const currValue = this.props.input.value || [];

    if (currValue.includes(b.value)) {
      // value already exists in array, let's remove it from there
      newValue = currValue.filter(val => val !== b.value);
    } else {
      // value doesn't exist in array, let's add it there
      newValue = currValue.concat([b.value]);
    }

    this.props.input.onChange(newValue);
  }

.filter().concat()之类的数组方法在这里是你的好处:它们返回新的数组实例,而不是改变现有的数组。

您的代码使用的是.push().splice(),这些方法很糟糕,因为它们会改变现有的数组。

您可以看到一个小型演示here

*您可以阅读有关此主题的更多信息here