You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React无限重渲染错误解决:角色权限控制场景

解决React组件无限重渲染问题(角色判断导致)

错误原因

你直接在组件渲染阶段调用setRole修改状态:每次组件渲染时,都会执行roles?.map里的逻辑并触发setRole,状态更新会再次触发组件渲染,形成无限循环,最终触发React的重渲染限制错误。

另外你的map逻辑还有漏洞:如果角色数组里有多个角色,只要最后一个不是LINACAPPOINTMENTMANAGER,role会被覆盖为false,哪怕前面有目标角色也会失效。

解决方案

不需要用useState存储角色判断结果,直接在渲染时计算即可(如果角色可能动态变化,用useMemo缓存结果):

方案1:直接计算(角色无动态变化场景)

替换原来的useState和map代码段,直接判断是否包含目标角色:

const authContext = useContext(AuthContext);
const roles = authContext.userData?.roleNames;

// 直接判断数组是否包含目标角色,默认返回false
const hasLinacManagerRole = roles?.includes('LINACAPPOINTMENTMANAGER') || false;

然后修改FormElement的disabled属性:

<FormElement
  {...sharedProps}
  type='select'
  label='selectmachineProposal'
  name='machine'
  options={machineQuery.data?.items}
  disabled={!hasLinacManagerRole} // 有角色则禁用为false(启用字段),无则为true(禁用字段)
/>

方案2:用useMemo缓存(角色可能动态变化场景)

如果角色会在组件生命周期中动态更新(比如用户切换角色),用useMemo缓存计算结果,避免不必要的重复计算:

import { FunctionComponent, useContext, useMemo } from 'react'; // 引入useMemo

// ...

const authContext = useContext(AuthContext);
const roles = authContext.userData?.roleNames;

// 仅当roles变化时重新计算结果
const hasLinacManagerRole = useMemo(() => {
  return roles?.includes('LINACAPPOINTMENTMANAGER') || false;
}, [roles]);

FormElement的disabled属性同上。

完整修改后的组件代码

import { Col, Divider, Row } from 'antd';
import moment from 'moment';
import { FunctionComponent, useContext, useMemo } from 'react';
import { useIntl } from 'react-intl';
import { useQuery } from 'react-query';
import index from '../../../../../api/nuclearMedicineApi/services/Index';
import Machine from '../../../../../api/nuclearMedicineApi/services/Machine';
import { dateFormat } from '../../../../../constants';
import { Index, MachineCategory, Priority, RadioTherapyByLinactStates } from '../../../../../constants/enums';
import { AuthContext } from '../../../../../contexts/auth-context';
import { IFormProps } from '../../../../../interfaces/form-props';
import { mapEnumToSelectValues } from '../../../../../utils/map-enum';
import FormElement from '../../../../common/form-element';
import StepsDiv from '../../../../common/steps';

interface RadioTherapyByLinacFormProps extends IFormProps { }

const RadioTherapyByLinacForm: FunctionComponent<RadioTherapyByLinacFormProps> = ({
    control,
    disabled,
    type,
    data
}) => {
    const sharedProps = {
        control,
        disabled,
    };

    const authContext = useContext(AuthContext);
    const roles = authContext.userData?.roleNames;

    const hasLinacManagerRole = useMemo(() => {
        return roles?.includes('LINACAPPOINTMENTMANAGER') || false;
    }, [roles]);

    const machineQuery = useQuery('machineGetAllLite', () =>
        Machine.machineGetAllLite({ machineCategory: MachineCategory.RadioTherapyByLinac }),
    );
    
    return (
        <>
            <Row>
                <Col span={12}>
                    <FormElement
                        {...sharedProps}
                        type='select'
                        label='selectmachineProposal'
                        name='machine'
                        options={machineQuery.data?.items}
                        disabled={!hasLinacManagerRole}
                    />
                </Col>
            </Row>
        </>
    );
};

export default RadioTherapyByLinacForm;

内容的提问来源于stack exchange,提问作者Hiba Youssef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:50:41