I have a project, and within this project I have several interfaces, and among these interfaces, I have an interface for creating a request, and this interface contains a field, and this field can be "disabled" or "not be disabled", when the role is "LINACAPPOINTMENTMANAGER" the field must be "disabled" Unless it's Enable.
And the role is an array of roles, that is, the user may have several roles and not just one role, and all roles must be traversed To check if the matrix contains an "LINACAPPOINTMENTMANAGER" role or not
I used "useState" named "role" and if the user is "LINACAPPOINTMENTMANAGER" it becomes true or false and on this basis I treat disabled
but i get this error:
Too many re-renders. React limits the number of renders to prevent an infinite loop.
How can i solve this problem?
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
CodePudding user response:
Maybe put the map in a useEffect would work?
useEffect(() => {
roles.forEach((r: string) => setRole(r === 'LINACAPPOINTMENTMANAGER'))
}, [roles])
Can you also clarify, if the role LINACAPPOINTMENTMANAGER is found, then the setRole is immediate true right? If that's the case, then forEach would not work because the loop will continue and might set it to false again if the next element is not LINACAPPOINTMENTMANAGER. In such case some would be the appropriate method.
CodePudding user response:
Why do you get this error?
When the component is rendered you're checking the roles
array for your specific role. As long as your roles
array is not empty, the setRole()
function is called within map()
. Attention: Updating a components state triggers a re-render of the component.
So the component gets re-rendered and again you come to the point where the roles
array is checked and setRole()
is called which triggers a re-render. And so on and so forth.
To avoid the rendering loop, put the setRole
function in a useEffect
that gets called only initially and if roles
change.
How to solve the issue?
Update the components state only at first render or if the roles array has changed.
useEffect(()=>{
let isManager = roles.some((r: string) => r === 'LINACAPPOINTMENTMANAGER');
setRole(isManager);
}, [roles]);
React documentation
Here is an example from the React documentation that addresses the effect of a state change: https://reactjs.org/docs/hooks-state.html#recap
CodePudding user response:
You can use useEffect.
useEffect(() => {
const unrole = roles.forEach((r: string) => setRole(r === 'LINACAPPOINTMENTMANAGER'))
//unmounting
return unrole
}, [roles])