在高阶组件中使用ref

时间:2018-12-30 16:48:38

标签: javascript reactjs

我有一个Table组件,我想附加ref

使用: Table.js

class Table extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rows: 1,
      dataLength: props.dataLength,
    }
    this.tableRef = React.createRef(); 
  }

  componentDidUpdate() {
    //using ref
    this.tableRef.current ..... //logic using ref
    this.state.rows ..... //some logic
  }

  render() {
    <TableContainer ref={this.tableRef} />
    <CustomPagination />
  }
}

这可以很好地工作,但是现在我的要求已经改变,我想通过对应用程序中的所有表进行分页来重用Table组件。我决定进行HOC withCustomPagination

使用: withCustomPagination.js HOC

import CustomPagination from 'path/to/file';

const withCustomPagination = tableRef => Component => {
  return class WithCustomPagination extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        rows: 1,
        dataLength: props.dataLength,
      }
    }

    componentDidUpdate() {
      tableRef.current.state ..... //logic using ref, Error for this line
      this.state.rows ..... //some logic
    }

    render() {
      return (
        <Component {...state} />
        <CustomPagination />
      )
    }
  }
}

export default withCustomPagination;

新的 Table.js

import withCustomPagination from '/path/to/file';

const ref = React.createRef();

const Table = props => (
  <TableContainer ref={ref} />
);

const WrappedTable = withCustomPagination(ref)(Table);

HOC withCustomPagination返回一个类WithCustomPagination,该类具有一个componentDidUpdate生命周期方法,该方法在逻辑上使用Table ref。因此,我尝试将在 Table.js 中创建的ref作为withCustomPagination的参数传递,即使用refTable无状态组件进行咖喱。

这种ref的使用是错误的,我得到了错误:TypeError: Cannot read property 'state' of null

我尝试使用转发参考,但是无法实现。

如何将表ref传递给withCustomPagination并能够在HOC中使用它?

2 个答案:

答案 0 :(得分:1)

在这种情况下,您可以使用useImperativeHandle

这意味着您必须转发ref并指定哪个函数或对象,或者... 您想与功能组件内部的ref共享。

这是我的Hoc示例:

import React from 'react';
import { View } from 'react-native';

export function CommonHoc(WrappedComponent) {

    const component = class extends React.Component {

         componentDidMount() {
           this.refs.myComponent.showAlert();

        }

        render() {
            return (
                <>
                    <WrappedComponent
                        ref='myComponent'
                        {...this.state}
                        {...this.props}
                    />
                </>
            );
        }
    };
    return component;
}

这是我的无状态组件

const HomeController=(props,ref)=> {

    useImperativeHandle(ref, () => ({

        showAlert() {
            alert("called");
        },
    }));

    return (
        <Text>home</Text>
    );
};
export default CommonHoc(forwardRef(HomeController));

答案 1 :(得分:0)

要么重组代码以使其不使用HOC,要么尝试使用React.forwardRef

  

引用未通过

     

高阶组件的惯例要通过   包装的组件的所有道具,这对引用不起作用。   那是因为ref并不是真正的道具,就像钥匙一样,   特别是由React。如果将ref添加到组件为   HOC的结果,引用是指最外层的实例   容器组件,而不是包装组件。

     

此问题的解决方案是使用React.forwardRef API   (在React 16.3中引入)。了解更多有关转发的信息   裁判部分。

通过Higher-Order Components: Refs Aren’t Passed Through

forwarding refs section中,有一些代码示例可用于将引用向下传递,但是尝试将其向上拉将失败:

  

警告:无状态功能组件无法提供引用。尝试访问此引用将失败。

在一个项目中,我们采用了不同的方法。有一个EnhancedTable组件可以处理所有分页逻辑,并且本身具有哑表组件和分页组件。它工作得很好,但这意味着您将不得不钻取道具(或使用Redux或Mobx之类的store库)并添加将处理分页选项的新道具。这将导致Table使用的一些重构,您必须更加明确,但我认为这是福音,而不是障碍。