Repository: Avaiga/taipy
File: frontend/taipy-gui/src/components/Taipy/MenuCtl.tsx (TypeScript)

Code before:

interface MenuCtlProps extends LovProps<string> {
    label?: string;
    width?: string;
    width_Mobile_?: string;
    onAction?: string;
    inactiveIds?: string[];
    defaultInactiveIds?: string;
    selected?: string[];
    defaultSelected?: string;
}

const MenuCtl = (props: MenuCtlProps) => {
    const { id, label, onAction, defaultLov = "", width = "15vw", width_Mobile_ = "85vw" } = props;
    const dispatch = useDispatch();
    const isMobile = useIsMobile();
    const module = useModule();

    const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
    const active = useDynamicProperty(props.active, props.defaultActive, true);

    useDispatchRequestUpdateOnFirstRender(dispatch, id, module, props.updateVars, props.updateVarName);

    const lovList = useLovListMemo(props.lov, defaultLov, true);

    const { inactiveIds, selected } = useMemo(() => {
        const result = {
            inactiveIds: [] as string[],
            selected: [] as string[],
        };

        if (props.inactiveIds) {
            result.inactiveIds = props.inactiveIds;
        } else if (props.defaultInactiveIds) {
            try {
                result.inactiveIds = JSON.parse(props.defaultInactiveIds) as string[];
            } catch {
                console.error("Failed to parse defaultInactiveIds");
            }
        }

        if (props.selected) {
            result.selected = props.selected;
        } else if (props.defaultSelected) {
            try {
                result.selected = JSON.parse(props.defaultSelected) as string[];
            } catch (error) {
                console.error("Failed to parse defaultSelected:", error);
            }
        }


Review comment (suggestion):
looks like there is no link between `inactiveIds` and `selected`, they should be in 2 separated `useMemo`

Code after:

interface MenuCtlProps extends LovProps<string> {
    label?: string;
    width?: string;
    width_Mobile_?: string;
    onAction?: string;
    inactiveIds?: string[];
    defaultInactiveIds?: string;
    selected?: string[];
    defaultSelected?: string;
}

const MenuCtl = (props: MenuCtlProps) => {
    const {id, label, onAction, defaultLov = "", width = "15vw", width_Mobile_ = "85vw"} = props;
    const dispatch = useDispatch();
    const isMobile = useIsMobile();
    const module = useModule();

    const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
    const active = useDynamicProperty(props.active, props.defaultActive, true);

    useDispatchRequestUpdateOnFirstRender(dispatch, id, module, props.updateVars, props.updateVarName);

    const lovList = useLovListMemo(props.lov, defaultLov, true);

    const inactiveIds = useMemo(() => {
        if (props.inactiveIds) {
            return props.inactiveIds;
        } else if (props.defaultInactiveIds) {
            try {
                return JSON.parse(props.defaultInactiveIds) as string[];
            } catch {
                console.error("Failed to parse defaultInactiveIds");
            }
        }
        return [] as string[];
    }, [props.inactiveIds, props.defaultInactiveIds]);

    const selected = useMemo(() => {
        if (props.selected) {
            return props.selected;
        } else if (props.defaultSelected) {
            try {
                return JSON.parse(props.defaultSelected) as string[];
            } catch (error) {
                console.error("Failed to parse defaultSelected:", error);
            }
        }
        return [] as string[];
    }, [props.selected, props.defaultSelected]);