Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I import useCombinedRefs (Implementing draggable columns) #2267

Closed
Liam-OShea opened this issue Jan 8, 2021 · 5 comments
Closed

How do I import useCombinedRefs (Implementing draggable columns) #2267

Liam-OShea opened this issue Jan 8, 2021 · 5 comments

Comments

@Liam-OShea
Copy link

Liam-OShea commented Jan 8, 2021

I am trying to implement the draggable columns with react-data-grid based on this example: https://github.com/adazzle/react-data-grid/blob/canary/stories/demos/ColumnsReordering.tsx

I see that this example requires creating a DraggableHeaderRenderer file, so I have copied the following file into my project and converted it to javascript: https://github.com/adazzle/react-data-grid/blob/canary/stories/demos/components/HeaderRenderers/DraggableHeaderRenderer.tsx

My issue is that I do not know where to import useCombinedRefs from. It is not exported from react-data-grid. I see in the repo that it resides in src/hooks.

I have tried the following:

import {useCombinedRefs} from 'react-data-grid'
// Error: Attempted import error: 'useCombinedRefs' is not exported from 'react-data-grid'.

import  {useCombinedRefs}  from 'react-data-grid/lib/hooks';
// Error: Module not found: Can't resolve 'react-data-grid/lib/hooks' in 'C:\Users\Liam\Desktop\Work\MyProject\src\ReactDataGrid'

import  useCombinedRefs  from 'react-data-grid/lib/hooks/useCombinedRefs';
// Error: Module not found: Can't resolve 'react-data-grid/lib/hooks/useCombinedRefs' in 'C:\Users\Liam\Desktop\Work\MyProject\src\ReactDataGrid'

Thanks to anyone who can help.

Here is my code:
DraggableHeaderRenderer.js

import { useDrag, useDrop } from 'react-dnd';
import React from 'react'

import { SortableHeaderCell } from 'react-data-grid';
import  useCombinedRefs  from 'react-data-grid/lib/hooks/useCombinedRefs';


export function DraggableHeaderRenderer({ onColumnsReorder, column, sortColumn, sortDirection, onSort }) {
  const [{ isDragging }, drag] = useDrag({
    item: { key: column.key, type: 'COLUMN_DRAG' },
    collect: monitor => ({
      isDragging: !!monitor.isDragging()
    })
  });

  const [{ isOver }, drop] = useDrop({
    accept: 'COLUMN_DRAG',
    drop({ key, type }) {
      if (type === 'COLUMN_DRAG') {
        onColumnsReorder(key, column.key);
      }
    },
    collect: monitor => ({
      isOver: !!monitor.isOver(),
      canDrop: !!monitor.canDrop()
    })
  });

  return (
    <div
      ref={useCombinedRefs(drag, drop)}
      style={{
        opacity: isDragging ? 0.5 : 1,
        backgroundColor: isOver ? '#ececec' : 'inherit',
        cursor: 'move'
      }}
    >
      <SortableHeaderCell
        column={column}
        sortColumn={sortColumn}
        sortDirection={sortDirection}
        onSort={onSort}
      >
        {column.name}
      </SortableHeaderCell>
    </div>
  );
}

TestDataGrid.js

import React from 'react';
import DataGrid from 'react-data-grid';
import {DraggableHeaderRenderer} from './DraggableHeaderRenderer';
import { useState, useCallback, useMemo } from 'react';
import 'react-data-grid/dist/react-data-grid.css';

const createRows = () => {
  const rows = [];
  for (let i = 1; i < 500; i++) {
    rows.push({
      id: i,
      task: `Task ${i}`,
      complete: Math.min(100, Math.round(Math.random() * 110)),
      priority: ['Critical', 'High', 'Medium', 'Low'][Math.round(Math.random() * 3)],
      issueType: ['Bug', 'Improvement', 'Epic', 'Story'][Math.round(Math.random() * 3)]
    });
  }

  return rows;
}

const createColumns = () => {
  return [
    {
      key: 'id',
      name: 'ID',
      width: 80,
    },
    {
      key: 'task',
      name: 'Title',
      resizable: true,
      sortable: true,
      draggable: true
    },
    {
      key: 'priority',
      name: 'Priority',
      resizable: true,
      sortable: true,
      draggable: true
    },
    {
      key: 'issueType',
      name: 'Issue Type',
      resizable: true,
      sortable: true,
      draggable: true
    },
    {
      key: 'complete',
      name: '% Complete',
      resizable: true,
      sortable: true,
      draggable: true
    }
  ];
}

export default function TestDataGrid() {

  const [rows] = useState(createRows)
  const [columns, setColumns] = useState(createColumns)

  const draggableColumns = useMemo(() => {
    const HeaderRenderer = (props) => {
      return <DraggableHeaderRenderer {...props} onColumnsReorder={handleColumnsReorder}/>
    }

    const handleColumnsReorder = (sourceKey, targetKey) => {
      const sourceColumnIndex = columns.findIndex(c => c.key === sourceKey);
      const targetColumnIndex = columns.findIndex(c => c.key === targetKey);
      const reorderedColumns = [...columns];

      reorderedColumns.splice(
        targetColumnIndex,
        0,
        reorderedColumns.splice(sourceColumnIndex, 1)[0]
      );

      setColumns(reorderedColumns);
    }

    return columns.map(c => {
      if(c.key === "id") return c;
      return {...c, HeaderRenderer}
    });
  }, [columns])



  return (
    <DataGrid
      columns={draggableColumns}
      rows={rows}
    />
  );
}
@yashjais18
Copy link

yashjais18 commented Jan 9, 2021

Hey I've found what the issue is. I've found a work around but I don't think it's a very good way.
The issue is they are not exporting useCombinedRefs. So you need to put that function in the code.
function useCombinedRefs(...refs) { return useCallback(handle => { for (const ref of refs) { if (typeof ref === 'function') { ref(handle); } else if (ref !== null) { ref.current = handle; } } }, refs); }
Put this function istead of importing it and you will be good to go. Sandbox link here.

@nstepien
Copy link
Contributor

useCombinedRefs is a private API and we don't plan on exporting it. You can either copy it over to your repo, or try and find an alternative on npm.

@Liam-OShea
Copy link
Author

@yashjais18 Thanks for your assistance! Your approach worked but I then ran into another issue down the road. I've decided to go with Prime Faces' Data Table for now.

@nstepien Thanks for providing clarity. Maybe a note should be made in the documentation regarding the origin of useCombinedRefs for anyone who is unaware.

@amanmahajan7
Copy link
Contributor

Here is the link for useCombinedRefs

@gormonn
Copy link

gormonn commented Jul 5, 2021

Hello!
I think it's better:
https://github.com/Torvin/react-ref-composer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants