React - 获取包装类组件的引用

时间:2018-01-04 01:33:49

标签: reactjs react-router higher-order-components

我有一个包含子侧边栏组件的地图组件。我正在尝试做一个相对简单的任务,即当点击它的地图标记时滚动到侧边栏中的地方列表中的位置。但是,由于侧边栏需要包含在withRouterconnect中,因此我无法在地图组件中设置参考(ref) => this.sidebar = ref

export class Map extends React.Component {
  ...

  handleClick() {
    this.sidebar.scrollToPlace(place.id);
  }

  render () {
    return (
      <MapSidebar
        // unable to set ref
      />
    )
  }
}

class MapSidebar extends React.Component {
  ...

  scrollToPlace(id) {
    this.refs[id].scrollIntoView({block: 'end', behavior: 'smooth'});
  }
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MapSidebar));

我知道使用wrappedComponentRef可以获取withRouter的内容,但我仍然需要connect来处理。

我还尝试在MapSidebar实例上创建自定义引用:

<MapSidebar
  getReference={(ref) => {
    this.sidebar = ref;
  }} />

然后在MapSidebar类构造函数中调用:

if(this.props.getReference) {
  this.props.getReference(this);
}

但是这导致了该组件更新的无限循环(虽然我不确定我理解为什么)。

有没有更好的方法解决这些问题?

2 个答案:

答案 0 :(得分:1)

我建议你避免引用并简单地传递滚动值:

export class Map extends React.Component {
  ...

  handleClick() {
    this.setState({scrollToPlaceId: place.id});
  }

  render () {
    return (
      <MapSidebar
        // Add a new property
        scrollToPlace={this.state.scrollToPlaceId}
      />
    )
  }
}

然后在侧边栏组件中,只需听取componentWillReceiveProps中的滚动更改,例如

class MapSidebar extends React.Component {
  ...

  componentWillReceiveProps(nextProps) {
    if (nextProps.scrollToPlace !== this.props.scrollToPlace) {
      this.refs[nextProps.scrollToPlace].scrollIntoView({block: 'end', behavior: 'smooth'});
    }
  }
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MapSidebar));

答案 1 :(得分:1)

在两个类中存储引用:

    SELECT * 
FROM CROSSTAB(
$$
    WITH month_index AS
    (
       SELECT rowid AS row_name,
       CONCAT(''m'',monthno) AS category,
       nic5dindex AS value
       FROM source_data_table
    )
    SELECT * FROM month_index 
,
   '*<categorysql>*'
$$   
   )
AS ct(..)

然后在地图渲染中:

// MapSidebar render - add this to the element you want.
<div ref={r => (this.ref = r)}>

现在,在Map安装完成后,您可以访问ref:

<MapSidebar ref={r => (this.sidebar = r)}>