自定义下拉字段组件与 Redux-Form 不兼容

Customized Dropdown Field Component not compatible with Redux-Form

我有以下问题。 我使用元素自定义了我自己的 DropDown 组件。 我希望此元素与 Redux-Form 交互,因为我想保存所选的值。 这不起作用:

<Field
name="name"
component={MyCustomizedDropDown}
data={myData}/>

另一种选择是使用 "input" 道具,但由于我使用的是元素,所以这是不可能的。 有人可以给我一个解决方案吗?谢谢

MyCustomizedDropDown 组件:

import React, { Component } from "react";
import PropTypes from "prop-types";

class MyCustomizedDropdown extends Component {
  constructor(props) {
    super(props);
    this.state = {
      ...this.props,
      items: this.props.items || [],
      selectedItem: this.props.items[0] || this.props.selectedItem,
      showItems: false,
      isOpened: false
    };
    this.dropDown = this.dropDown.bind(this);
    this.selectedItem = this.selectedItem.bind(this);
  }

  dropDown() {
    this.setState(prevState => ({
      showItems: !prevState.showItems
    }));
  }

  selectedItem(item) {
    this.setState({
      selectedItem: item,
      showItems: false
    });
  }

  render() {
    const { input } = this.props;
    return (
      <div className="select-box--wrapper">
        <div className="select-box--toggle" onClick={this.dropDown}>
          <div className="select-box--selected-item">
            {this.state.selectedItem && this.state.selectedItem.value}
          </div>
          <MyImage
            className={`${
              this.state.showItems
                ? "select-box--arrow-rotated"
                : "select-box--arrow"
            }`}
          />
        </div>
        <div className="select-box--main">
          <div
            {...input} \THIS DOES NOT WORK
            className="select-box--items">
            {this.state.data.map(item => (
              <div key={item.id} onClick={() => this.selectedItem(item)}>
                {item.value}
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }
}


MyCustomizedDropdown.propTypes = {
  data: PropTypes.array,
  selectedItem: PropTypes.array,
  input: PropTypes.object
};

export default MyCustomizedDropdown;

您不应该在输入状态下处理输入值。 MyCustomizedDropDown 应该接收 handleChange 函数,itemsselectedItem 作为属性。唯一应该处于组件状态的是它是否打开。

redux-form 仅适用于 "controlled" 组件。这意味着该组件需要一个父级用来告诉它它的值是什么的道具。比如下面是一个受控组件:

<TextField 
  value={this.state.inputValue} 
  onChange={(value) => this.setState({ inputValue: value })} 
/>

请注意,我们告诉 TextField 组件它的值是什么。您需要更改组件才能以相同的方式工作。这里唯一需要注意的是,redux-form 注入了一个名为 input 的 prop,它是一个包含 valueonChange(以及其他一些东西)的对象,而不是直接注入 valueonChange.

所以对于上面的例子,它需要这样工作才能支持redux-form:

<TextField 
  input={{
    value: this.state.inputValue,
    onChange: (value) => this.setState({ inputValue: value })
  }}
/>

这是你的组件,写成 "controlled" 组件,以一种应该与 redux-form 一起工作的方式:

import React, { Component } from "react";
import PropTypes from "prop-types";

class MyCustomizedDropdown extends Component {
  constructor(props) {
    super(props);
    this.state = {
      showItems: false
    };
    this.dropDown = this.dropDown.bind(this);
    this.selectedItem = this.selectedItem.bind(this);
  }

  dropDown() {
    this.setState(prevState => ({
      showItems: !prevState.showItems
    }));
  }

  hideDropdownItems() {
    this.setState({
      showItems: false
    });
  }

  render() {
    const { input } = this.props;
    return (
      <div className="select-box--wrapper">
        <div className="select-box--toggle" onClick={this.dropDown}>
          <div className="select-box--selected-item">
            {this.input.value && this.input.value.value}
          </div>
          <MyImage
            className={`${
              this.state.showItems
                ? "select-box--arrow-rotated"
                : "select-box--arrow"
            }`}
          />
        </div>
        <div className="select-box--main">
          <div
            className="select-box--items">
            {this.state.data.map(item => (
              <div 
                key={item.id} 
                onClick={() => {
                  this.input.onChange(item)
                  this.hideDropdownItems();
                }}
              >
                {item.value}
              </div>
            ))}
          </div>
        </div>
      </div>
    );
  }
}


MyCustomizedDropdown.propTypes = {
  data: PropTypes.array,
  selectedItem: PropTypes.array,
  input: PropTypes.object
};

export default MyCustomizedDropdown;
  • 请注意,我们告诉 MyCustomizedDropdown 它的价值在使用 this.props.input.value
  • 如果组件想要更改它的值,我们会调用 this.props.input.onChange。由于它不能自己完成,它需要告诉它的父级它想要更改值。
  • 家长需要回应onChange并更新MyCustomizedDropdown的值

例如,如果没有 redux-form:

,这就是您使用组件的方式
<MyCustomizedDropdown 
  input={{
    value: this.state.dropDownValue,
    onChange: (value) => this.setState({ dropDownValue: value })
  }}
/>

使用 redux-form,您只需执行以下操作,因为 redux-form 会为您管理所有这些内容:

<Field
  component={MyCustomizedDropdown}
/>