React警告:渲染DataTable时无法更新AssignTeacherForAttendance组件
求助:解决React警告“Cannot update a component (
AssignTeacherForAttendance) while rendering a different component (DataTable)” 我遇到了React警告:Cannot update a component ('AssignTeacherForAttendance') while rendering a different component ('DataTable')。
警告截图:
以下是我的代码:
import { getAuthToken } from '../../utils/auth'; import { API } from '../../config/api/api.config'; import axios from 'axios'; import { resHandlerNoSuccess, responseHandler } from '../../utils/responseHandler'; import { CCard, CCardBody, CCardTitle, CFormInput, CFormLabel } from '@coreui/react'; import { Button } from 'primereact/button'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Calendar } from 'primereact/calendar'; import { Dropdown } from 'primereact/dropdown'; import { Form, redirect, useActionData, useLoaderData, useNavigation, useSearchParams, useSubmit, } from 'react-router-dom'; import { getStandardDropdownLoader } from '../standard/AddSection'; import React, { useCallback, useEffect, useState } from 'react'; import { getSectionDropdownLoader } from '../student/AddStudent'; import { classNames } from 'primereact/utils'; const SectionAccessTable = React.memo(({ sectionAccess, onAccessTypeSort }) => { return ( <DataTable value={sectionAccess ? sectionAccess?.section_access : []} tableStyle={{ marginLeft: '4px', marginTop: '4px', borderTop: '1px solid #cccccc' }} size="small" removableSort paginator rows={50} emptyMessage="No section access found" > <Column header="#" body={(data, options) => options.rowIndex + 1} style={{ width: '5%' }} ></Column> <Column field="standard" header="Standard"></Column> <Column field="section_name" header="Section"></Column> <Column field="faculty_name" header="Faculty"></Column> <Column field="user_type" header="User Type"></Column> <Column field="from" header="From" sortable></Column> <Column field="to" header="to" sortable></Column> <Column field="access_type" header="Access Type" sortable sortFunction={onAccessTypeSort} ></Column> <Column header="Action"></Column> </DataTable> ); }); const AssignTeacherForAttendance = () => { // 获取hooks数据 const { standards, section, faculty, sectionAccess } = useLoaderData(); const actionData = useActionData(); let [searchParams, setSearchParams] = useSearchParams(); let submit = useSubmit(); // 初始化状态 const [perPage, setPerPage] = useState(50); const [pageNumber, setPageNumber] = useState(1); const [sortField, setSortField] = useState(''); const [sortOrder, setSortOrder] = useState('ASC'); // 表单数据状态 const [standardSelected, setStandardSelected] = useState(null); const [sectionSelected, setSectionSelected] = useState(null); const [facultySelected, setFacultySelected] = useState(null); const [accessTypeSelected, setAccessTypeSelected] = useState(null); const [fromDate, setFromDate] = useState(null); const [toDate, setToDate] = useState(null); // 访问类型选项 const accessType = [ { access_type: 'same_day' }, { access_type: 'all_day' }, { access_type: 'range_day' }, ]; // 操作成功后重置表单 useEffect(() => { if (actionData?.success === true) { setStandardSelected(null); setSectionSelected(null); setFacultySelected(null); setAccessTypeSelected(null); setFromDate(null); setToDate(null); } }, [actionData]); // 选择标准后更新搜索参数 useEffect(() => { if (!standardSelected) return; setSearchParams({ standard_id: standardSelected }); }, [standardSelected]); // 提交表单 const onAssignFaculty = useCallback(() => { submit( { section_id: sectionSelected, faculty_id: facultySelected, access_type: accessTypeSelected, from: fromDate, to: toDate, }, { method: 'post', encType: 'application/json' }, ); }, [sectionSelected, facultySelected, accessTypeSelected, fromDate, toDate, submit]); // 访问类型排序逻辑 const onAccessTypeSort = useCallback(({ data, field, order }) => { console.log('>> sorting called'); const orderNow = order === 1 ? 'ASC' : order === -1 ? 'DESC' : ''; setSortField(field); setSortOrder(orderNow); }, []); return ( <> <div> <form className="flex justify-content-start p-1 flex-wrap"> <div className="pr-1"> <Dropdown value={standardSelected} onChange={(e) => setStandardSelected(e.value)} options={standards ? standards : []} placeholder="Select standard" className={`w-full md:w-11rem p-inputtext-sm`} optionValue="id" optionLabel="standard" /> </div> <div className="pr-1"> <Dropdown value={sectionSelected} onChange={(e) => setSectionSelected(e.value)} options={section ? section : []} placeholder="Select section" className="md:w-11rem p-inputtext-sm" optionValue="id" optionLabel="section_name" /> </div> <div className="pr-1"> <Dropdown value={facultySelected} onChange={(e) => setFacultySelected(e.value)} options={faculty ? faculty : []} placeholder="Select Faculty" optionLabel="full_name" className="md:w-11rem p-inputtext-sm" optionValue="id" /> </div> <div className="pr-1"> <Dropdown value={accessTypeSelected} onChange={(e) => setAccessTypeSelected(e.value)} options={accessType ? accessType : []} placeholder="Access Type" className="md:w-10rem p-inputtext-sm" optionValue="access_type" optionLabel="access_type" /> </div> <div className="pr-1"> <Calendar value={fromDate} onChange={(e) => setFromDate(e.value)} className="md:w-6rem p-inputtext-sm " placeholder="From" // touchUI /> </div> <div className="pr-1"> <Calendar value={toDate} onChange={(e) => setToDate(e.value)} className="md:w-6rem p-inputtext-sm " placeholder="To" // touchUI /> </div> <Button label="Assign" severity="success" type="button" // disabled={isSubmitting} raised // loading={isSubmitting} size="small" onClick={onAssignFaculty} /> </form> <SectionAccessTable sectionAccess={sectionAccess} onAccessTypeSort={onAccessTypeSort} /> </div> </> ); }; export default AssignTeacherForAttendance; async function getFacultyDropdownLoader() { const token = getAuthToken(); const facultyDropdownResponse = await axios({ url: API.endpoint + '/user/faculty-dropdown', headers: { 'Content-Type': 'application/json', Authorization: token, }, validateStatus: () => true, }); return resHandlerNoSuccess(facultyDropdownResponse); } async function getSectionAccessList({ sort_field, sort_order, per_page, page_number, search_term, }) { const token = getAuthToken(); const response = await axios({ url: API.endpoint + '/section-access/list-all', params: { per_page: per_page ? per_page : 50, sort_order: sort_order ? sort_order : 'ASC', sort_field: sort_field ? sort_field : '', page_number: page_number ? page_number : 1, }, headers: { 'Content-Type': 'application/json', Authorization: token, }, validateStatus: () => true, }); return resHandlerNoSuccess(response); } export async function loader({ request }) { const url = new URL(request.url); const standardId = url.searchParams.get('standard_id'); const per_page = url.searchParams.get('per_page'); const sort_order = url.searchParams.get('sort_order'); const sort_field = url.searchParams.get('sort_field'); const page_number = url.searchParams.get('page_number'); const facultyDropdown = await getFacultyDropdownLoader(); const standardList = await getStandardDropdownLoader(); const sectionAccessList = await getSectionAccessList({ per_page, sort_order, sort_field, page_number, }); if (facultyDropdown.redirect) return redirect(facultyDropdown.redirect); if (standardList.redirect) return redirect(standardList.redirect); if (sectionAccessList.redirect) return redirect(sectionAccessList.redirect); if (standardId) { const sectionDropdownGot = await getSectionDropdownLoader(standardId); if (sectionDropdownGot.redirect) return redirect(sectionDropdownGot.redirect); return { section: sectionDropdownGot.data, standards: standardList.data, faculty: facultyDropdown.data?.faculty, sectionAccess: sectionAccessList.data, }; } return { standards: standardList.data, faculty: facultyDropdown.data?.faculty, sectionAccess: sectionAccessList.data, }; } export async function action({ request, params }) { const token = getAuthToken(); const data = await request.json(); const responseGot = await axios.post( API.endpoint + '/section-access/assign-for-attendance', { ...data, }, { headers: { 'Content-Type': 'application/json', Authorization: token, }, validateStatus: () => true, }, ); if (!responseGot) return null; const responseHandled = responseHandler(responseGot); if (responseHandled.redirect) return redirect(responseHandled.redirect); return responseHandled.data; }
我已查阅GitHub相关issue及多个StackOverflow问题,但仍未找到解决方案。
已尝试的优化操作:
- 在过滤函数中添加回调
- 将DataTable迁移到独立组件
- 使用React.memo优化SectionAccessTable的渲染
恳请帮助解决该问题。
内容的提问来源于stack exchange,提问作者Divya
相关产品推荐
相关产品推荐

