TonyGermaneri / canvas-datagrid

Canvas based data grid web component. Capable of displaying millions of contiguous hierarchical rows and columns without paging or loading, on a single canvas element.
BSD 3-Clause "New" or "Revised" License
1.42k stars 184 forks source link

Using canvas-datagrid in React #548

Open romanstetsyk opened 1 year ago

romanstetsyk commented 1 year ago

Does anyone have a working example of using canvas-datagrid with React and TypeScript? There is a tutorial with an example that uses react@15.5.4, but I couldn't figure out how to convert it to modern syntax. Here is a codesandbox with my attempt. It doesn't work as expected: the allowSorting option is not working, and data accepts a stringified array, not just an array. There's also no way to add event listeners with this implementation. I would appreciate it if someone gave me some pointers on how to use it correctly in React. Thanks

ndrsn commented 1 year ago

Hi @romanstetsyk , my apologies for the late reply. We most definitely need to update the documentation, good point. I'll try to make some time for that later this week.

It's not obvious from the documentation, but the reason why allowSorting isn't working in this example is because the schema for that header isn't defined, and when it doesn't know the type it doesn't know how to sort on it; it'll try a string sort (using localeCompare), but falls short of actually converting the value (1) to a string, and since Numbers don't have a localeCompare property it simply won't sort. A bit stupid.

As for how to add event listeners, you'll need to set those imperatively. I've set up a short example here, using React hooks instead of class components (we're still in the process of upgrading to React hooks at work, so I might not have all the details right). The gist is using useEffect to set up the grid on mount (including even listeners), and using useEffect to explicitly set data on change.

ndrsn commented 1 year ago

Let me know if you have any other questions, I've got some more time to respond now, and happy to help — would like to update docs to make use of modern React, so if you find anything lacking let me know.

In the future, we'd like to offer a (type-safe) wrapper for React, but haven't had the time for that yet :-)

romanstetsyk commented 1 year ago

Hi @ndrsn, thanks for your reply! This is something similar I came up with. However, I created a ref in a parent component and used forwardRef to access the grid's data in a parent component. This is to make it possible to update the state after pasting data into the grid. afterpaste event provides access to the changed cells but not the new values. Do you think it's a good approach?

I also noticed that some events, like afterrendercell, beforerendercell, rendertext etc., are triggered on a mouse move. I'm not sure if it's intended behavior.

romanstetsyk commented 1 year ago

Is there any way to use node_modules/canvas-datagrid/dist/types.d.ts? Or should I create an interface for props by manually copying data from that file?

ndrsn commented 1 year ago

Is there any way to use node_modules/canvas-datagrid/dist/types.d.ts? Or should I create an interface for props by manually copying data from that file?

How do you mean 'use' ? It's been a while since any part of that code's changed, but that file is listed in package.json under types — does that not work?

ndrsn commented 1 year ago

This is to make it possible to update the state after pasting data into the grid. afterpaste event provides access to the changed cells but not the new values. Do you think it's a good approach?

I think that makes sense — My afterpaste handler uses the cells to look up the new values in grid.data, but if the data is included in the event handler that wouldn't be necessary, I guess.

I also noticed that some events, like afterrendercell, beforerendercell, rendertext etc., are triggered on a mouse move. I'm not sure if it's intended behavior.

I'm not the original author, so I can't speak with full certainty, but it seems acceptable to me that rendering logic is triggered on mouse move (and thus events like afterrendercell, beforerendercell, rendertext, etc are fired), because you may want to change (for instance) styling of certain cells based on where the cursor is located.

romanstetsyk commented 1 year ago

How do you mean 'use' ? It's been a while since any part of that code's changed, but that file is listed in package.json under types — does that not work?

Sorry, it wasn't a thoughtful question. I look into this package through the prism of React. I'm trying to create a reusable wrapper with all the supported attributes, properties, and events and was searching for easy ways to add types 😅.

ndrsn commented 1 year ago

Even less thoughtful questions are welcome :) The types file is generated based on the JSDoc annotations, but I'm not sure how well we're actually checking the types. I'm going to upgrade the build system this week to get rid of webpack and rollup in favor of vite, and I'll see if I can do something about the types.

A reusable wrapper for React would be most welcome! It's been on the roadmap for ages, but I felt better tests and types would have to come first. Luckily, I have some more time now to spend on that.

romanstetsyk commented 1 year ago

I'm going to upgrade the build system this week to get rid of webpack and rollup in favor of vite

That sounds like a fantastic idea! Should we expect a version update soon?

Edit: just noticed it's already updated!