Skip to content

[Table] Cell render triggers the render of the whole table #10088

@coolassassin

Description

@coolassassin

Provide a general summary of the issue here

Hello everyone!

We are using react-aria-components to simplify a11y support in our application, but we have faced performance issues in our case.
We are working with trading UIs, and there are many cases where you need to show changes in the Cell very fast.
To make it cheap, we are subscribing to data in each Cell and render Cells only to avoid huge recalculations.
But, we found out that Table in react-aria-components conflicts with this approach.
For example, if I add the Cell like so:

function VolatileNumericCell() {
  const [value, setValue] = useState(() => Math.random())

  useEffect(() => {
    const id = window.setInterval(() => {
      setValue(Math.random())
    }, 1000)
    return () => {
      window.clearInterval(id)
    }
  }, [])

  return <Cell className={'numeric'}>{value.toFixed(6)}</Cell>
}

It is just a Simple Cell, which rerenders itself every second. But, this Cell will trigger the whole table, which can be easily detected with React Dev Tools

I can fix it like so:

function VolatileNumericCell2() {
  const [value, setValue] = useState(() => Math.random())

  useEffect(() => {
    const id = window.setInterval(() => {
      setValue(Math.random())
    }, 1000)
    return () => {
      window.clearInterval(id)
    }
  }, [])

  return value.toFixed(6)
}

And then Render like so:

<Cell className={'numeric'}>
     <VolatileNumericCell2 />
</Cell>

This approach fixes behavior, but it is not a really convenient way to work with, especially if you want to make the Cell appearance dynamic

As I understand, the problem is:

  • setProps triggers queueUpdate in the document
  • These changes through useSyncExternalStore trigger the whole table

🤔 Expected Behavior?

If Render Cell only, it renders only Cell

😯 Current Behavior

Any Cell renders triggers the render of the whole Table

💁 Possible Solution

Find out the way to update the table model (document) only in cases when it is necessary, or add some Eq or memoisation

🔦 Context

I am trying to create a big table with many-many cells, which updates itself by subscribing to some data outside. The table is absolutely static in this task, but the cells are very dynamic

🖥️ Steps to Reproduce

Create any table layout and add Cell like so:

function VolatileNumericCell() {
  const [value, setValue] = useState(() => Math.random())

  useEffect(() => {
    const id = window.setInterval(() => {
      setValue(Math.random())
    }, 1000)
    return () => {
      window.clearInterval(id)
    }
  }, [])

  return <Cell>{value.toFixed(6)}</Cell>
}

Example for storybook

Version

1.17.0

What browsers are you seeing the problem on?

Chrome

If other, please specify.

No response

What operating system are you using?

Mac OS

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions