3
votes

Trying to implement a custom cell framework renderer with React and it seems simple enough. Create the React component, register it with frameworkComponents.

The data that populates rowData is coming from my redux store. The custom cell renderer is a functional react component.

The issue is that because I'm using a frameworkComponent - a React component in my case - as a cellRenderer, it seems that any change in the data for the grid the I'm getting via useSelector(selectorForMyData) causes a re-render of my frameworkComponent, which on the browser, looks like a random, annoying flicker. The application is heavily wired into redux

Two questions:

1 - How come when I natively use ag grid to render this cell using a AgGridColumn without any custom cell renderers, it doesn't cause this re-rendering behavior on the same store changes? I have a click event bound to the main page that toggles a flag to false (in the case a snackbar alert was open).

2 - Is there any way to get around this? I've tried wrapping my return statement in the framework cell renderer component with a useMemo with the params as a dependency, but that doesn't seem to work. Also tried making a render function via useCallback with the same idea as useMemo and that doesn't help either :/

Thanks

pseudo-code for situation:

App.tsx:

<MyAgGrid/>

MyAgrid.tsx:


const MyAgGrid = () => {
 const data = useSelector(selectorForData);
 return (
   <AgGridReact
     rowData={data}
     frameworkComponents={
       {'myCustomRenderer': CustomRendererComponent}
     }
     columnDefs={
       ['field': 'aField', cellRenderer: 'myCustomRenderer']
     } />
   );
};


CustomCellRendererComponent.tsx:

const CustomCellRendererComponent = (params) => {
  console.log("params", params) //logs on every redux store update
  return (
    <div>HELLO WORLD</div>
  );
};


The cells that are rendered via the CustomCellRendererComponent are re-rendered on any redux store change. I'm guessing it's due to useSelector causing the re-render on store changes, which is expected, but then it doesn't answer my first question.

EDIT: I went "function as class" route shown here ("MyCellRenderer") and so far am not seeing the re-rendering issue, so I will stick with that for now even though it's god ugly. This leads me to believe my issue is trying to fit a React component/hooks, with its lifecycle nuances, as a cell renderer is causing problems. Still, I feel like there should be a way to prevent the behavior of constant re-rendering, otherwise it's a pretty useless feature

EDIT pt 2: I dug deeper and while I haven't found an out of the box solution for it, I added the reselect library to memoize some of my selectors. The selector I use to get rowData is now memoized, and I'm no longer seeing this issue. Will mark as answer in a few days if no one provides a better, ideally out of the box (with redux or ag grid), solution for it.

1
Adding the relevant code to your question would be helpful. - Ed Lucas
@EdLucas Definitely agree, I added a very dumbed down / pseudo code for it. It'd be a bit of work to get a whole playground set up for it w/ the redux boilerplate stuff and all :/ Not sure why my comment isn't tagging you, sorry. - mclslee

1 Answers

0
votes

As I stated in one of my edits. I figured it out, kind of.

I added the library reselect to the application, and it fixes the symptoms and I'm content with it going forward. It allows you to memoize your selectors, so that it only registers changes/"fires" (leading to a re-render) only if the any of the dependency selectors you hook it into changes/fires, so now, my grid doesn't "flicker" until the actual row data changes since my selectorForRowData is memoized!

I'm still uncertain why prior to using a frameworkComponent (React Component) as a cell renderer I wasn't seeing the symptoms, but I'm happy to just assume Ag-Grid has a lot of performance tricks that clients may lose when plugging in their own custom functionality, as is the case in a custom cell renderer.