HaveSpacesuit
HaveSpacesuit

Reputation: 3994

Prevent Component Flicker in React State Update

I load data for a table in a two-step process. The first load gets the basic info for the table. The second load goes row by row with more data-intensive queries. When the query returns, we update the row's info, then call setItems([...data]) to rerender the table with the updated data from the row.

The problem is that this causes a flicker when hovering a link in the row, as the entire table is re-rendered every second or so as the next row's data comes in.

Here is the relevant code from my useData hook:

const [items, setItems] = useState<T[]>([] as T[])

const data = await fetchPrimaryData()
setItems(data)

for (const item of data) {
  await secondaryRequest(item) // secondary request mutates item
  setItems([...data])
}

If you remove the second setItems, the data gets updated, but the state is not updated until you start clicking around and causing a refresh some other way.

My preference would be to just re-render the row which has been updated, but since the table relies on a data: T[] prop, anytime part of the data changes, the whole table re-renders and causes the flicker.

Upvotes: 2

Views: 5502

Answers (1)

Jawad ul hassan
Jawad ul hassan

Reputation: 575

One possible solution could be, useCallback hook. It will solve your problem of unnecessary re-rendering. i.e.

const [items, setItems] = useState<T[]>([] as T[])


const loadPrimaryData = useCallback(async () => {
 const data = await fetchPrimaryData();
 setItems(data);
}, []);

const loadSecondaryData = useCallback(async () => {
 for (const item of data) {
  await secondaryRequest(item)
  setItems([...data])
}}, [data]);

Further, if you want to load data one after another, depending on your use-case, you can use useEffect hook.

Upvotes: 2

Related Questions