Tanstack react-query与react-table:为何引发无限重渲染?
React Query与React Table联用导致无限重渲染的原因及解决方法
问题重现
以下代码会导致App组件无限重渲染,控制台持续输出component triggered:
import React from 'react' import { QueryClient, QueryClientProvider, useQuery } from 'react-query' import { useReactTable, createColumnHelper, getCoreRowModel } from '@tanstack/react-table' const queryClient = new QueryClient() const columnHelper = createColumnHelper() const columns = [ columnHelper.accessor('thing', { header: 'thing', cell: () => '' }) ] const AppContextWrapper = () => { return ( <QueryClientProvider client={queryClient}> <App /> </QueryClientProvider> ) } const App = () => { const query = useQuery(['test'], () => '') const table = useReactTable({ data: [], columns, getCoreRowModel: getCoreRowModel() }) console.log('component triggered') return table.getRowModel().rows.length } export default AppContextWrapper
原因分析
核心问题出在useReactTable的配置项getCoreRowModel: getCoreRowModel():
- 每次
App组件渲染时,getCoreRowModel()都会被调用,生成一个全新的函数实例。 useReactTable会对比配置项的引用变化,当getCoreRowModel的引用改变时,会重新计算表格实例,进而触发组件重渲染。- 组件重渲染又会再次调用
getCoreRowModel()生成新实例,形成无限循环。
另外,useQuery的状态切换(从loading到success)会触发第一次重渲染,而上述循环逻辑会让重渲染持续下去。
解决方法
将getCoreRowModel()的结果缓存起来,避免每次渲染生成新实例:
方案1:将核心模型函数移到组件外部
因为getCoreRowModel()的结果是静态的,不需要依赖组件内部状态,可以直接在组件外定义:
// 移到组件外部,只初始化一次 const coreRowModel = getCoreRowModel() const App = () => { const query = useQuery(['test'], () => '') const table = useReactTable({ data: [], columns, getCoreRowModel: coreRowModel }) console.log('component triggered') return table.getRowModel().rows.length }
方案2:用useMemo包裹(适合依赖组件内部状态的场景)
如果getCoreRowModel需要依赖组件内的变量,可以用useMemo缓存:
const App = () => { const query = useQuery(['test'], () => '') const coreRowModel = React.useMemo(() => getCoreRowModel(), []) const table = useReactTable({ data: [], columns, getCoreRowModel: coreRowModel }) console.log('component triggered') return table.getRowModel().rows.length }
额外注意事项
- 确保
useReactTable配置中的所有函数(如getCoreRowModel、getFilteredRowModel等)都不会在每次渲染时生成新实例。 - 静态配置项(如
columns)尽量放在组件外部,避免不必要的引用变化。
内容的提问来源于stack exchange,提问作者Andy Pandy
相关产品推荐
相关产品推荐

