Commit 9b60bf72e37cbebe4d6a7cdf5167fccc7d4993b3
1 parent
2900cc7c
chore(usr): FE-03 门禁回归通过 REQ-USR-003
Showing
2 changed files
with
13 additions
and
4 deletions
frontend/src/pages/usr/UserList/useUserList.ts
| @@ -51,6 +51,9 @@ export function useUserList(): UseUserListReturn { | @@ -51,6 +51,9 @@ export function useUserList(): UseUserListReturn { | ||
| 51 | const messageRef = useRef(message); | 51 | const messageRef = useRef(message); |
| 52 | messageRef.current = message; | 52 | messageRef.current = message; |
| 53 | 53 | ||
| 54 | + // 卸载守卫:避免异步取数 resolve/reject 在组件卸载后 setState(防内存泄漏 / 测试环境拆除后报错) | ||
| 55 | + const mountedRef = useRef(true); | ||
| 56 | + | ||
| 54 | /** 以给定 query 取数;同步 total/pageNum/pageSize 回显(BR15);错误码分流(spec § 4) */ | 57 | /** 以给定 query 取数;同步 total/pageNum/pageSize 回显(BR15);错误码分流(spec § 4) */ |
| 55 | const runFetch = useCallback(async (q: UserListQuery) => { | 58 | const runFetch = useCallback(async (q: UserListQuery) => { |
| 56 | setQuery(q); | 59 | setQuery(q); |
| @@ -59,6 +62,7 @@ export function useUserList(): UseUserListReturn { | @@ -59,6 +62,7 @@ export function useUserList(): UseUserListReturn { | ||
| 59 | setError(null); | 62 | setError(null); |
| 60 | try { | 63 | try { |
| 61 | const pageData = await listUsers(q); | 64 | const pageData = await listUsers(q); |
| 65 | + if (!mountedRef.current) return; | ||
| 62 | setList(pageData.records); | 66 | setList(pageData.records); |
| 63 | setTotal(pageData.total); | 67 | setTotal(pageData.total); |
| 64 | // 信任后端回显(越界回退最后一页等),同步分页当前页/页大小(BR15) | 68 | // 信任后端回显(越界回退最后一页等),同步分页当前页/页大小(BR15) |
| @@ -69,6 +73,7 @@ export function useUserList(): UseUserListReturn { | @@ -69,6 +73,7 @@ export function useUserList(): UseUserListReturn { | ||
| 69 | }); | 73 | }); |
| 70 | setLoading(false); | 74 | setLoading(false); |
| 71 | } catch (err) { | 75 | } catch (err) { |
| 76 | + if (!mountedRef.current) return; | ||
| 72 | const apiErr = err instanceof ApiError ? err : new ApiError(-1, TEXT_MSG_NETWORK); | 77 | const apiErr = err instanceof ApiError ? err : new ApiError(-1, TEXT_MSG_NETWORK); |
| 73 | setLoading(false); | 78 | setLoading(false); |
| 74 | if (apiErr.code === ERR_PAGE_INVALID) { | 79 | if (apiErr.code === ERR_PAGE_INVALID) { |
| @@ -92,7 +97,11 @@ export function useUserList(): UseUserListReturn { | @@ -92,7 +97,11 @@ export function useUserList(): UseUserListReturn { | ||
| 92 | 97 | ||
| 93 | // 挂载即以默认条件取数(initialLoading,BR2) | 98 | // 挂载即以默认条件取数(initialLoading,BR2) |
| 94 | useEffect(() => { | 99 | useEffect(() => { |
| 100 | + mountedRef.current = true; | ||
| 95 | void runFetch({ ...DEFAULT_QUERY }); | 101 | void runFetch({ ...DEFAULT_QUERY }); |
| 102 | + return () => { | ||
| 103 | + mountedRef.current = false; | ||
| 104 | + }; | ||
| 96 | // eslint-disable-next-line react-hooks/exhaustive-deps | 105 | // eslint-disable-next-line react-hooks/exhaustive-deps |
| 97 | }, []); | 106 | }, []); |
| 98 | 107 | ||
| @@ -140,11 +149,11 @@ export function useUserList(): UseUserListReturn { | @@ -140,11 +149,11 @@ export function useUserList(): UseUserListReturn { | ||
| 140 | const pageData = await listUsers({ ...cur, pageNum: 1, pageSize: fetchSize }); | 149 | const pageData = await listUsers({ ...cur, pageNum: 1, pageSize: fetchSize }); |
| 141 | const csv = buildUserCsv(pageData.records); | 150 | const csv = buildUserCsv(pageData.records); |
| 142 | downloadCsv(EXPORT_FILENAME, csv); | 151 | downloadCsv(EXPORT_FILENAME, csv); |
| 143 | - messageRef.current.success(TEXT_EXPORT_SUCCESS); | 152 | + if (mountedRef.current) messageRef.current.success(TEXT_EXPORT_SUCCESS); |
| 144 | } catch { | 153 | } catch { |
| 145 | - messageRef.current.error(TEXT_EXPORT_FAIL); | 154 | + if (mountedRef.current) messageRef.current.error(TEXT_EXPORT_FAIL); |
| 146 | } finally { | 155 | } finally { |
| 147 | - setExporting(false); | 156 | + if (mountedRef.current) setExporting(false); |
| 148 | } | 157 | } |
| 149 | }, [total]); | 158 | }, [total]); |
| 150 | 159 |
frontend/tests/unit/UserTable.test.tsx
| 1 | // REQ-USR-003: UserTable 表格单测(BR1/BR6/BR11/BR12/BR14/D8) | 1 | // REQ-USR-003: UserTable 表格单测(BR1/BR6/BR11/BR12/BR14/D8) |
| 2 | import { describe, it, expect, vi, beforeEach } from 'vitest'; | 2 | import { describe, it, expect, vi, beforeEach } from 'vitest'; |
| 3 | -import { screen, within } from '@testing-library/react'; | 3 | +import { screen } from '@testing-library/react'; |
| 4 | import userEvent from '@testing-library/user-event'; | 4 | import userEvent from '@testing-library/user-event'; |
| 5 | import { renderShell } from './renderShell'; | 5 | import { renderShell } from './renderShell'; |
| 6 | import UserTable from '../../src/pages/usr/UserList/UserTable'; | 6 | import UserTable from '../../src/pages/usr/UserList/UserTable'; |