T
TanStack2y ago
quickest-silver

How to memoize flexRender?

I want to prevent cells from rerendering when cell props does not change. I think problem is in flexRender function, but can not find way to memoize it. I added memo to custom cell input, useMemo to columns.
6 Replies
exotic-emerald
exotic-emerald2y ago
Hi. We had this problem in SolidJS, this is the solution we came up with in our project:
export interface CellRendererProps<TProps extends object> {
/** The cell content (e.g. component/string) render */
readonly component: ColumnDefTemplate<TProps> | undefined;
/** The props to pass to the cell component */
readonly props: TProps;
}

/**
* Renders the TanStack Table's cell. A substitute for \@tanstack/solid-table's flexRender method.
*
* flexRender uses Solid's internal createComponent method, which does not memoize the component.
* This means that every time the table is re-rendered, the component is re-created.
* That's why we need to use Dynamic, which uses Solid's createMemo under the hood.
*/
export const CellRenderer = <TProps extends object>(props: VoidProps<CellRendererProps<TProps>>): JSX.Element => (
<Show when={props.component}>
<Show
when={typeof props.component === "function"}
// The TS inference does not work in <Show>, so we need to manually cast it to a string.
fallback={props.component as string}
>
<Dynamic component={props.component} {...props.props} />
</Show>
</Show>
);
export interface CellRendererProps<TProps extends object> {
/** The cell content (e.g. component/string) render */
readonly component: ColumnDefTemplate<TProps> | undefined;
/** The props to pass to the cell component */
readonly props: TProps;
}

/**
* Renders the TanStack Table's cell. A substitute for \@tanstack/solid-table's flexRender method.
*
* flexRender uses Solid's internal createComponent method, which does not memoize the component.
* This means that every time the table is re-rendered, the component is re-created.
* That's why we need to use Dynamic, which uses Solid's createMemo under the hood.
*/
export const CellRenderer = <TProps extends object>(props: VoidProps<CellRendererProps<TProps>>): JSX.Element => (
<Show when={props.component}>
<Show
when={typeof props.component === "function"}
// The TS inference does not work in <Show>, so we need to manually cast it to a string.
fallback={props.component as string}
>
<Dynamic component={props.component} {...props.props} />
</Show>
</Show>
);
And then:
<Index each={row().getVisibleCells()}>
{(cell) => (
<span class={s.cell}>
<CellRenderer component={cell().column.columnDef.cell} props={cell().getContext()} />
</span>
)}
</Index>
<Index each={row().getVisibleCells()}>
{(cell) => (
<span class={s.cell}>
<CellRenderer component={cell().column.columnDef.cell} props={cell().getContext()} />
</span>
)}
</Index>
evident-indigo
evident-indigo2y ago
Is it react example? What are <Show/> and <Dynamic/>?
exotic-emerald
exotic-emerald2y ago
Sorry, no, this is SolidJS. I forgot this is not the standard.
evident-indigo
evident-indigo2y ago
I try to do the same using React,wrapping cell's content in usememo, but it doesn't help(
stormy-gold
stormy-gold2y ago
Is there any reason for this, do you actually see a perf issue at this moment?
evident-indigo
evident-indigo2y ago
Yeah, I want to prevent extra retenders unchanged rows/cells

Did you find this page helpful?