user2465134
user2465134

Reputation: 9793

React Using Correct Memo for Table Column Mapping

I have a React component that uses HandsOnTable to render a table (not necessarily important to the issue but figured I'd give context).

Every time the component renders the table, it runs a renderer function on every column header to handle formatting. I want to memoize the this function pumping out the columns because tables can have 100+ columns and the renderer/formatter it getting very expensive on the big tables.

const getSettings = () => {
  // getSettings only runs once or twice, but getTableColumns will run once for every column
  return {
    columns: getTableColumns
  }
}

const getTableColumns = (index) => {
  const column = data[index]

  const renderer = () => {
    // expensive formatting using the column data
  }

  return {
    renderer
  }
}

I'm unsure which to use, memo, useMemo, useCallback; I'm new to the memo situation in React. Also, I've read the React versions of memo aren't like actual memo like in lodash? Here is what I've tried:

columns: useMemo(() => getHotColumns, [props.selectedNode])

This unfortunately throws an error: Invalid hook call. Hooks can only be called inside of the body of a function component.

Every time the user selects a new node on my graph UI I want to rerender my table to handle the new data, aka when props.selectedNode changes.

Upvotes: 0

Views: 962

Answers (1)

John Paul R
John Paul R

Reputation: 752

The quick version:

It sounds to me like what you actually want here is to memoize the output of each renderer invocation. That could looks something like this:

// This is the important bit, we are caching the rendered output for each column
const renderedColumns = useMemo(() => {
  const renderer = (columnData) => {
    // expensive formatting using the column data
  }

  return your_column_data.map(renderer);
}, [your_column_data]);

const getTableColumns = (index) => {
  // Return the cached value instead of re-calculating
  return renderedColumns[index];
};

// This memoization sounds like it is less important, but it doesn't hurt.
const columnSettings = useMemo(() => ({
  columns: getTableColumns
}), [getTableColumns]);

I'm unsure which to use, memo, useMemo, useCallback

Quick overview, as I understand it:

  • memo - Memoizes a React component. This means that it won't rerender unless one of its props change. (normally, if the parent rerenders, so will the child)
  • useMemo computes and caches a value until one of the values in the specified dependencies array changes, in which case it will recalculate using the provided function.
  • useCallback afaik this is identical to useMemo, just has a cleaner interface for memoizing functions.

Upvotes: 1

Related Questions