SonarQube "Do not define components during render" with MUI/TS but can't send component as prop
Asked Answered
P

1

6

I am getting the following error during sonarqube scan:

Do not define components during render. React will see a new component type on every render and destroy the entire subtree’s DOM nodes and state. Instead, move this component definition out of the parent component “SectionTab” and pass data as props. If you want to allow component creation in props, set allowAsProps option to true.

enter image description here

I understand that it says that I should send the component as a prop from the parent, but I don't want to send the icon everytime that I want to use this component, is there another way to get this fixed?

import Select from "@mui/material/Select";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleDown } from "@fortawesome/pro-solid-svg-icons/faAngleDown";

const AngleIcon = ({ props }: { props: any }) => {
  return (
    <FontAwesomeIcon
      {...props}
      sx={{ marginRight: "10px" }}
      icon={faAngleDown}
      size="xs"
    />
  );
};

const SectionTab = () => {
  return (
    <Select
      id="course_type"
      readOnly={true}
      IconComponent={(props) => <AngleIcon props={props} />}
      variant="standard"
      defaultValue="cr"
      disableUnderline
    />
  );
};

export default SectionTab;
Proximity answered 10/2, 2023 at 16:57 Comment(0)
W
11

What can you do:

  1. Send the component as the prop:

    IconComponent={AngleIcon}
    
  2. If you need to pass anything to the component on the fly, you can wrap it with useCallback:

    const SectionTab = () => {
        const IconComponent = useCallback(props => <AngleIcon props={props} />, []);
    
       return (
         <Select
           id="course_type"
           readOnly={true}
           IconComponent={IconComponent}
           variant="standard"
           defaultValue="cr"
           disableUnderline
         />
       );
     };
    

This would generate a stable component, but it's pretty redundant unless you need to pass anything else, and not via the props. In that case, a new component would be generated every time that external value changes, which would make it unstable again. You can use refs to pass values without generating a new component, but the component's tree won't be re-rendered to reflect the change in the ref.

const SectionTab = () => {
  const [value, setValue] = useState(0);
  
  const IconComponent = useCallback(
    props => <AngleIcon props={props} value={value} />
  , []);

  return (
    <Select
      id="course_type"
      readOnly={true}
      IconComponent={IconComponent}
      variant="standard"
      defaultValue="cr"
      disableUnderline
    />
  );
};
Wiseman answered 10/2, 2023 at 17:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.