React-Table+Redux数据渲染失败:页面空白及更新深度溢出问题排查
问题排查:React-Table结合Redux渲染空白+更新深度超限错误
问题描述
使用React-Table展示Redux中的用户数据时,页面呈现空白状态,数据无法正常渲染,同时控制台抛出Uncaught Error: Maximum update depth exceeded错误,怀疑问题出在columns、data变量定义或useTable调用逻辑上。
代码片段
import React, { useState, useEffect, useMemo } from 'react'; import { useTable } from 'react-table'; import { useDispatch, useSelector } from 'react-redux'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { COLUMNS } from './Column'; import NavigationDashbooard from './UsersNavigationBigScreen'; import Button from '../components/Button'; import { loading } from '../assets'; import { fetchingAllUsers } from '../states/features/users/usersSlice'; import NavigationDashboardSmall from './UsersNavigationSmallScreen'; const AdminManageUserContainer = () => { const dispatch = useDispatch(); const { isPending, totalpages, userList, networkError } = useSelector( (state) => { return state.users; } ); const columns = useMemo(() => { return (COLUMNS, []) }); const data = useMemo(() => { return (userList, []) }); const tableInstance = useTable({ columns: columns, data: data }); const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = tableInstance; useEffect(() => { dispatch(fetchingAllUsers(1)); }, []); return ( <div className='manage_accounts_wrapper h-screen'> <NavigationDashbooard /> <div className='manage_accounts_content'> <h1 className='bigTitle_users mt-10'>Manage Users</h1> <div className='createUserBox mb-10'> <h1 className='listOfUsers '>List of users</h1> <Button className='primary-btn create_user_btn' value='+ Add user' route='/' onClick={() => {}} /> <Button className='create_user_btn_small' value='+' route='/' onClick={() => {}} /> </div> <div className='manage_accounts_content_table h-4.5/6'> <table {...getTableProps()}> <thead> {headerGroups.map((headerGroup) => { return ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map((column) => { return ( <th {...column.getHeaderProps()}> {column.render('Header')} </th> ); })} </tr> ); })} </thead> <tbody {...getTableBodyProps()}> {rows.map((row) => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.cells.map((cell ) => { return ( <td {...cell.getCellProps()}>{cell.render('Cell')}</td> ); })} </tr> ); })} </tbody> </table> {isPending && ( <div className='loading_div w-full'> Loading... <img src={loading} alt='' /> </div> )} {networkError && ( <div className='loading_div w-full'> Server or Network Error{' '} <FontAwesomeIcon icon='fa-solid fa-exclamation-circle' /> </div> )} </div> </div> <NavigationDashboardSmall /> </div> ); }; export default AdminManageUserContainer;
错误分析
- useMemo返回值逻辑错误:使用了逗号表达式
(COLUMNS, [])和(userList, []),这类表达式会返回最后一个值(即空数组),导致columns和data始终为空,表格没有表头和数据,页面呈现空白。 - 无限重渲染触发深度超限:
useMemo的依赖项数组为空,且每次渲染都会返回新的空数组(引用地址不同),导致useTable每次都接收到新的columns和data参数,触发表格实例重新创建,进而引发组件无限重渲染,最终抛出Maximum update depth exceeded错误。
修复方案
修正useMemo的返回逻辑和依赖项:
// 正确返回COLUMNS常量,依赖项为空(COLUMNS是静态导入的常量,不会变化) const columns = useMemo(() => COLUMNS, []); // 正确返回userList,添加userList作为依赖项确保Redux数据更新时同步;用|| []处理userList初始为undefined的情况 const data = useMemo(() => userList || [], [userList]);
修复后说明
columns:直接返回导入的COLUMNS常量,依赖项为空数组,确保仅在组件首次渲染时计算一次。data:返回userList或空数组,依赖项设为userList,当Redux中的userList更新时,data会重新计算,useTable会自动更新表格数据。- 上述修改解决了表格空白和无限重渲染的问题,同时保证Redux数据更新时表格能同步刷新。
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

