Redux Store触发无限重渲染,组件更新项目列表遇难题求助
问题分析与解决方案
核心问题
- 类中使用React Hooks违规:你在
MissionService类的构造函数里调用了useAppSelector和useAppDispatch,这违反了React Hooks的规则——Hooks只能在函数组件顶层或自定义Hook中使用,类组件/普通类里用Hooks会导致不可预测的行为。 - useEffect无限循环:把
projectsList放进依赖数组后,每次调用getProjects都会dispatch更新projectsList,触发组件重渲染,进而再次触发useEffect调用getProjects,形成无限循环。
修复步骤
1. 重构MissionService为自定义Hook
放弃类形式的服务,改用符合React规则的自定义Hook,避免在类中使用Hooks:
import { useAppDispatch } from '../store/hooks'; import { useCallback } from 'react'; import backendAPI from './api'; import { setProjectList } from '../store/slices/xprojSlice'; import { KeycloakInstance } from 'keycloak-js'; export const useMissionService = (keycloak: KeycloakInstance) => { const dispatch = useAppDispatch(); // 用useCallback稳定函数引用,避免不必要的重触发 const getProjects = useCallback(async () => { if (!keycloak.token) return; backendAPI.defaults.headers.common['Authorization'] = `Bearer ${keycloak.token}`; try { const { data } = await backendAPI.get('/mission/user'); dispatch(setProjectList(data)); } catch (error: any) { errorNotification(error.response.data.message); } }, [keycloak.token, dispatch]); return { getProjects }; };
2. 修正组件中的useEffect逻辑
移除projectsList作为依赖,改为在组件挂载时调用一次getProjects,并在新建项目成功后主动刷新列表:
import { useAppSelector } from '../store/hooks'; import { useMissionService } from './useMissionService'; import { keycloak } from './keycloak'; // 假设你的keycloak实例在这里 const ProjectListComponent = () => { const { projectsList } = useAppSelector((state) => state.xproj); const { getProjects } = useMissionService(keycloak); // 组件挂载时初始化数据 useEffect(() => { getProjects(); }, [getProjects]); // getProjects已被useCallback稳定,只会触发一次 // 新建项目的处理函数,成功后主动刷新列表 const handleCreateProject = async (projectData) => { try { // 调用新建项目的API await backendAPI.post('/mission', projectData); // 新建成功后刷新项目列表 getProjects(); } catch (error) { // 处理新建错误 } }; return ( // 组件渲染内容 ); };
为什么这样有效
- 自定义Hook遵循了React Hooks的规则,避免了类中使用Hooks的错误。
useCallback保证了getProjects的引用稳定,useEffect只会在组件挂载时执行一次初始化请求。- 新建项目后主动调用
getProjects,既能更新列表,又不会触发无限循环。
内容的提问来源于stack exchange,提问作者Mark Philips
相关产品推荐
相关产品推荐

