React中如何控制useEffect触发时机避免无效请求?
问题
我正在设置React中useEffect钩子内函数的触发时机以控制组件渲染。需要通过登录用户的ID(作为交易表的外键)在表格中渲染该用户的交易记录,但登录时仅能获取用户名、密码和access token,因此只能通过登录时的用户名调用接口获取包含ID在内的完整用户信息。
目前功能可运行,但组件会发起约3次请求,其中前两次因传入的ID为undefined而失败。
相关代码如下:
import React, { useContext } from 'react' import { useEffect } from 'react'; import Table from 'react-bootstrap/Table'; import { CdrsContext } from '../contexts/CDRDownloadingContext'; import { UserContext } from '../contexts/UserContext'; import UseAuth from '../hooks/UseAuth'; import styles from './stylePages/CDRDownloading.module.css' const CDRTable = () => { const { getUserDetails, record } = useContext(UserContext) const { cdrListFiltered, getCdrsListMadeByUser } = useContext(CdrsContext); const { auth } = UseAuth(); /************************************* * GETTING THE USER ID TO GET THE LIST OF REPORT REQUESTS SENT BY THE SPECIFIC USER //*************************************/ // Auth.username is providin an object type user from the backend, which among the properties // it contains the user id. const extractedUsername = auth.username; console.log(extractedUsername); // Once the user details have been loaded with the getUserDetails(extractedUsername); function which expects a username to get data. // I get the especific user and with the record const extractedUserById = record.serie; console.log(extractedUserById) //**************************************/ /** * Function to mount the list of report requests made by the logged in user */ useEffect(() => { getUserDetails(extractedUsername); getCdrsListMadeByUser(extractedUserById) }, [extractedUserById]); const typeReport = { 0: 'Cliente', 1: 'Proveedor' } const callFilter = { 0: 'Contestadas', 1: 'No contestadas', 2: 'Todas' } return ( <> <div> <br /> </div> <Table className={styles.table}> <thead className={styles.tableHead}> <tr> <th>ID</th> <th>FECHA CONSULTA</th> {/* <th>ID USUARIO</th> */} <th>EMAIL</th> <th>FECHA INICIAL</th> <th>FECHA FINAL</th> <th>TIPO REPORTE</th> <th>NOMBRE CLIENTE/PROVEEDOR</th> <th>RGIDs</th> <th>ESTADO</th> <th>PROCESO INICIADO</th> <th>PROCESO FINALIZADO</th> <th>FILTRO LLAMADA</th> </tr> </thead> <tbody> {cdrListFiltered?.map((report, reportIndex) => ( <tr key={reportIndex} > <td>{reportIndex + 1}</td> <td>{report.requestDate}</td> {/* <td>{report.requestUserId}</td> */} <td>{report.requestEmail}</td> <td>{report.startDate}</td> <td>{report.endDate}</td> <td>{typeReport[report.reportType]}</td> <td>{report.contactId}</td> <td>{report.rgids}</td> <td>{report.status}</td> <td>{report.processStart}</td> <td>{report.processFinish}</td> <td>{callFilter[report.callQuery]}</td> </tr> ) )} </tbody> </Table> </> ) } export default CDRTable
请问如何避免这种情况,实现仅在用户ID就绪时再触发请求并渲染,而非在首次渲染时就调用?
解决方案
拆分请求流程,保证依赖顺序
把获取用户详情和请求交易记录的逻辑拆成两个独立的useEffect,先确保拿到完整用户信息,再发起交易记录请求:// 先获取用户详情 useEffect(() => { if (extractedUsername) { getUserDetails(extractedUsername); } }, [extractedUsername]); // 用户ID就绪后,再请求交易记录 useEffect(() => { if (extractedUserById) { getCdrsListMadeByUser(extractedUserById); } }, [extractedUserById]);添加参数校验,拦截无效请求
在调用接口前先判断参数是否存在,只有当extractedUsername和extractedUserById不为undefined时才发起请求,从源头避免无效调用。优化依赖数组
原代码的useEffect依赖extractedUserById,首次渲染时该值为undefined会触发无效请求。拆分后第一个useEffect依赖extractedUsername,确保登录后用户名存在就触发用户详情请求;第二个依赖extractedUserById,确保ID存在才触发交易记录请求。可选:增加加载状态提升体验
在UserContext中添加加载状态,当用户详情正在获取时,组件显示加载提示,避免空表格或错误状态:// 从上下文获取加载状态 const { getUserDetails, record, loading } = useContext(UserContext); // 渲染时优先显示加载提示 if (loading) { return <div>加载中...</div>; }
内容的提问来源于stack exchange,提问作者Rosh343
相关产品推荐
相关产品推荐

