How to access refs with react-sortable-hoc, withref

I tried using the "withref" in react-sortable-hoc and I need to have my parent component access the children components for some calls I need to invoke on the parent side. I'm not sure where to even call the getWrappedInstance, which seems to be providing access to the children component.

I'm aware of forwarding but it seems like react-sortable-hoc have a different implementation.

To be more specific, I have something like this:

const SortableItem = SortableElement((props) => (
  <div className="sortable">
    <MyElement {...props}/>
  </div>
), {withRef: true});
const MidasSortableContainer = SortableContainer(({ children }: { children: any }) => {
  return <div>{children}</div>;
}, {withRef: true});
<MySortableContainer
  axis="xy"
  onSortEnd={this.onSortEnd}
  useDragHandle
>{chartDivs}</MySortableContainer>

Before I wrapped in HOC, I was able to do the following from MySorat

const chartDivs = elements.map(({childName}, index) => {
      return <MyElement
              ref={r => this.refsCollection[childName] = r}
...

Does anyone have any ideas how to achieve the same after wrapping with HOC? Thanks.

1 answer

  • answered 2020-01-14 03:53 tomioion

    You can get ref of children component with HOC Component getWrappedInstance function

    from source code: https://github.com/clauderic/react-sortable-hoc/blob/master/src/SortableElement/index.js#L82

    SortableElement hoc function with config = {withRef: false} config will create public function getWrappedInstance to its return HOC SortableElement Component

    So when you get HOC SortableElement Element ref, then use ref.getWrappedInstance() to get true element dom reference

    Here is example from official example (use class component to function component, function component should use forwardRef to ref props):

    import React, {Component} from 'react';
    import {render} from 'react-dom';
    import {SortableContainer, SortableElement} from 'react-sortable-hoc';
    import arrayMove from 'array-move';
    
    const SortableItem = SortableElement(({value}) => <li>{value}</li>);
    
    const SortableList = SortableContainer(class extends Component {
      render () {
        const items = this.props.items
    
        return (
          <ul>
            {items.map((value, index) => (
              <SortableItem key={`item-${value}`} index={index} value={value} />
            ))}
          </ul>
        );
      }
    }, { withRef: true });
    
    class SortableComponent extends Component {
      state = {
        items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'],
      };
    
      componentDidMount() {
        // get container ref here
        const refContainer = this.refs.listContainer
    
        // get container dom
        const dom = refContainer.getWrappedInstance() // Get dom!
      }
    
      onSortEnd = ({oldIndex, newIndex}) => {
        this.setState(({items}) => ({
          items: arrayMove(items, oldIndex, newIndex),
        }));
      };
      render() {
        return <SortableList ref='listContainer' items={this.state.items} onSortEnd={this.onSortEnd} />;
      }
    }
    
    render(<SortableComponent />, document.getElementById('root'));
    

    Form example above, you can get list container dom from SortableComponent Component, element dom is similar.