Reputation: 3994
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
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