typescript 未捕获的错误:重新呈现太多,React限制呈现次数以防止无限循环

ycggw6v2  于 2023-01-06  发布在  TypeScript
关注(0)|答案(3)|浏览(116)

我有一个项目,在这个项目中我有几个接口,在这些接口中,我有一个创建请求的接口,这个接口包含一个字段,这个字段可以是“disabled”或“not be disabled”,当角色是“LINACAPPOINTMENTMANAGER”时,这个字段必须是“disabled”,除非它是Enable.
并且角色是一个角色数组,即用户可能有多个角色,而不是只有一个角色,必须遍历所有角色,检查矩阵中是否包含“LINACAPPOINTMENTMANAGER”角色
我使用了名为“role”的“useState”,如果用户是“LINACAPPOINTMENTMANAGER”,它将变为true或false,并在此基础上将其视为disabled
但我得到这个错误:

Too many re-renders. React limits the number of renders to prevent an infinite loop.

我怎样才能解决这个问题?

import { Col, Divider, Row } from 'antd';
import moment from 'moment';
import { FunctionComponent, useContext, useState } 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;

    console.log('authContext: ', roles);
    const [role, setRole] = useState(false);
    {
        roles?.map((r: string, index) => {
            if (r === 'LINACAPPOINTMENTMANAGER') {
                setRole(true);
            }
            else {
                setRole(false);
            }
        })
    }

    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={role === true ? false : true}
                    />
                </Col>

            </Row>
        </>
    );
};

export default RadioTherapyByLinacForm;

// mapper for
//creatorUserId: 2
//lastModifierUserId: null
nfs0ujit

nfs0ujit1#

为什么会出现此错误?

当组件呈现时,您需要检查roles数组是否为您的特定角色。只要您的roles数组不为空,setRole()函数就会在map()中调用。注意:更新组件状态会触发组件的重新呈现。
所以组件被重新渲染,然后你又回到了检查roles数组,调用setRole(),触发重新渲染的地方,等等。
为了避免渲染循环,请将setRole函数放入useEffect中,该函数仅在roles发生更改时才调用。

如何解决该问题?

仅在第一次渲染时或角色数组已更改时更新组件状态。

useEffect(()=>{
   let isManager = roles.some((r: string) => r === 'LINACAPPOINTMENTMANAGER');
   setRole(isManager);
}, [roles]);
React文档

下面是React文档中的一个示例,它解决了状态更改的影响:https://reactjs.org/docs/hooks-state.html#recap

f2uvfpb9

f2uvfpb92#

也许把Map放在一个useEffect中会起作用?

useEffect(() => {
   roles.forEach((r: string) => setRole(r === 'LINACAPPOINTMENTMANAGER'))
}, [roles])

你还能澄清一下吗,如果找到了角色LINACAPPOINTMENTMANAGER,那么setRole就立即为true,对吗?如果是这种情况,那么forEach将不起作用,因为循环将继续,并且如果下一个元素不是LINACAPPOINTMENTMANAGER,可能会再次将其设置为false。在这种情况下,一些方法将是合适的方法。

to94eoyn

to94eoyn3#

您可以使用useEffect。

useEffect(() => {
  const unrole = roles.forEach((r: string) => setRole(r === 'LINACAPPOINTMENTMANAGER'))

  //unmounting
  return unrole
}, [roles])

相关问题