【问题标题】:Redux connect() removes function that my component needs [duplicate]Redux connect() 删除了我的组件需要的功能[重复]
【发布时间】:2018-04-04 05:04:37
【问题描述】:

我无法确定最好的策略是保留原始组件的功能(特别是 setSelected() 使用 Redux 的 connect() 将其包装成更高阶的功能时。我正在使用我的前端应用程序的单选按钮的一组很棒的组件:

Radio.js

class Radio extends React.Component {
  constructor(props) {
    super(props);
    this.state = {selected: props.selected};
  }

  toggle() {
    console.log(this.context)
    const {onChange} = this.context.radioGroup;
    const selected = !this.state.selected;
    this.setState({selected});
  //  this.props.changeRadioGroupState(this.props.option);
    onChange(selected, this);
  }

  setSelected(selected) {
    this.setState({selected});

  }


  render() {

    const activeStyle = {
      opacity: 0.1
    }
    const grayStyle = {
      opacity: 0.5
    }
    let classname = 'form__big_button'
    return (
      <button type="button"
      className={classname}
      onClick={this.toggle.bind(this)}
      style={this.state.selected ? activeStyle : grayStyle }>
        {this.props.option}
      </button>
    );
  }
}


Radio.contextTypes = {
  radioGroup: React.PropTypes.object
};

它有一个名为RadioGroup.js的父组件:

import React from 'react';

class RadioGroup extends React.Component {
  constructor(props) {
    super(props);
    this.options = [];

    this.changeRadioGroupState = this.changeRadioGroupState.bind(this);
  }

  getChildContext() {
    const {name} = this.props;
    return {radioGroup: {
      name,
      onChange: this.onChange.bind(this)
    }};
  }

  changeRadioGroupState(selectedOption){
     this.setState({selectedOption: selectedOption});
  }

  onChange(selected, child) {
    console.log(this.options)
    this.options.forEach(option => {
      if (option !== child) {
        option.setSelected(!selected);
      }
    });
  }

  render() {
    let children = React.Children.map(this.props.children, child => {


      let newElement = React.cloneElement(child, {
        ref: (component => {this.options.push(component);})
      });


      return newElement;
    });
    return <div className="radio-group">{children}</div>;
  }
}

RadioGroup.childContextTypes = {
  radioGroup: React.PropTypes.object
};

export default RadioGroup;

一起,它的渲染非常简单:

<RadioGroup>
  <Radio id="1" selected={true} option="Opt1"/>
  <Radio id="2" selected={false} option="Opt2"/>
</RadioGroup>

但是,我想将 Radio 连接到我的 Redux 存储,以便更新选定的单选按钮:

const mapStateToProps = (state) => {
  return {searchType: state.searchType}
}


export default connect(mapStateToProps)(Radio);

但是,这会导致浏览器出错:

Uncaught TypeError: option.setSelected is not a function
    at eval (RadioGroup.js?6ccb:27)
    at Array.forEach (<anonymous>)
    at RadioGroup.onChange (RadioGroup.js?6ccb:25)
    at Radio.toggle (Radio.js?9dd4:17)
    at Object.ReactErrorUtils.invokeGuardedCallback (ReactErrorUtils.js?9efc:71)
    at executeDispatch (EventPluginUtils.js?68fe:79)
    at Object.executeDispatchesInOrder (EventPluginUtils.js?68fe:102)
    at executeDispatchesAndRelease (EventPluginHub.js?daec:43)
    at executeDispatchesAndReleaseTopLevel (EventPluginHub.js?daec:54)
    at Array.forEach (<anonymous>)

这显然是connect() 组件包装了我的Radio 组件的结果——它不再公开setSelected() 函数。使用 Redux connect() 函数将原始组件包装在高阶组件中时,保留原始组件功能的最佳方法是什么?

我在构造函数中尝试了this.setSelected = this.setSelected.bind(this) 绑定,但看起来connect() 函数返回了完全不同类型的对象——Connect 对象。

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    当您使用 Redux 并使用 ref 时,您应该传递连接选项参数withRef(它是第四个参数)。 您的连接将如下所示: export default connect(mapStateToProps, null, null, { withRef: true })(Radio);

    然后,您将能够通过以下方式访问组件的功能: option.getWrappedInstance().setSelected(!selected);

    您可以查看 react-redux 文档 here

    但我认为这种方法不是很好,我不建议过度使用 refs,也许尝试将 selected 作为 prop 传递给父 RadioGroup 以获得更整洁的解决方案。

    【讨论】:

    • 这很好用。谢谢你。你能解释一下为什么你不建议过度使用 refs 吗?
    • 当然。主要是因为它是一种在常规生命周期之外修改孩子的方法。这有点像不推荐的 jQuery 方法。你可以看看 react docs reactjs.org/docs/refs-and-the-dom.html#dont-overuse-refs 看看他们是怎么说的
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    相关资源
    最近更新 更多