From 7346eecb80b4796967a694bf74fc82eec2b24b6f Mon Sep 17 00:00:00 2001 From: FARAN Date: Mon, 21 Jul 2025 16:02:57 +0500 Subject: [PATCH 1/5] [Fix]: #1849 your apps menu item inactive --- client/packages/lowcoder/src/pages/ApplicationV2/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx index 14bf9df2e..20ba7f5ab 100644 --- a/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx +++ b/client/packages/lowcoder/src/pages/ApplicationV2/index.tsx @@ -176,6 +176,7 @@ export default function ApplicationHome() { routePath: ALL_APPLICATIONS_URL, routeComp: HomeView, icon: ({ selected, ...otherProps }) => selected ? : , + onSelected: (_, currentPath) => currentPath === ALL_APPLICATIONS_URL || currentPath.startsWith("/folder"), }, ], }, From 64b7f587e71db0e37a71e72bdbd04e51fcaa65b8 Mon Sep 17 00:00:00 2001 From: FARAN Date: Mon, 21 Jul 2025 16:19:33 +0500 Subject: [PATCH 2/5] [Fix]: #1849 remove common settings --- .../lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx b/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx index a9998fa5d..e6d2a79a4 100644 --- a/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx +++ b/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx @@ -110,9 +110,7 @@ export function AdvancedSetting() { } }, [canLeave]); - useEffect(() => { - dispatch(fetchCommonSettings({ orgId: currentUser.currentOrgId })); - }, [currentUser.currentOrgId, dispatch]); + const handleSave = (key: keyof typeof settings, onSuccess?: () => void) => { return (value?: any) => { From 52fe5485509571e1355355678a71ecab93dfc9fb Mon Sep 17 00:00:00 2001 From: FARAN Date: Mon, 21 Jul 2025 17:29:16 +0500 Subject: [PATCH 3/5] [Fix]: #1849 optimize api calls for advanced setting page --- .../pages/setting/advanced/AdvancedSetting.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx b/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx index e6d2a79a4..5a85dd6e5 100644 --- a/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx +++ b/client/packages/lowcoder/src/pages/setting/advanced/AdvancedSetting.tsx @@ -96,9 +96,18 @@ export function AdvancedSetting() { }, [currentUser.currentOrgId]) useEffect(() => { - dispatch(fetchCommonSettings({ orgId: currentUser.currentOrgId })); - dispatch(fetchAllApplications({})); - }, [currentUser.currentOrgId, dispatch]); + // Only fetch common settings if not already loaded + if (Object.keys(commonSettings).length === 0) { + dispatch(fetchCommonSettings({ orgId: currentUser.currentOrgId })); + } + }, [currentUser.currentOrgId, dispatch, commonSettings]); + + // Lazy load applications only when dropdown is opened + const handleDropdownOpen = () => { + if (appList.length === 0) { + dispatch(fetchAllApplications({})); + } + }; useEffect(() => { setSettings(commonSettings); @@ -176,6 +185,9 @@ export function AdvancedSetting() { onChange={(value: string) => { setSettings((v) => ({ ...v, defaultHomePage: value })); }} + onDropdownVisibleChange={(open) => { + if (open) handleDropdownOpen(); + }} options={appListOptions} filterOption={(input, option) => (option?.label as string).includes(input)} /> From 49370f942c11ab219c62d664e25b23e1cfc03627 Mon Sep 17 00:00:00 2001 From: FARAN Date: Mon, 21 Jul 2025 21:59:29 +0500 Subject: [PATCH 4/5] [Fix]: #1849 add useDebouncedValue hook, and fix chars length --- .../src/pages/ApplicationV2/FolderView.tsx | 16 ++++++++-------- .../src/pages/ApplicationV2/HomeView.tsx | 17 +++++++++-------- .../src/pages/ApplicationV2/TrashView.tsx | 18 +++++++++--------- .../src/pages/datasource/datasourceList.tsx | 17 +++++++++-------- .../src/pages/queryLibrary/LeftNav.tsx | 16 ++++++++-------- client/packages/lowcoder/src/util/hooks.ts | 19 +++++++++++++++++++ 6 files changed, 62 insertions(+), 41 deletions(-) diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/FolderView.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/FolderView.tsx index 887a74cc1..701685711 100644 --- a/client/packages/lowcoder/src/pages/ApplicationV2/FolderView.tsx +++ b/client/packages/lowcoder/src/pages/ApplicationV2/FolderView.tsx @@ -1,7 +1,8 @@ import { useDispatch, useSelector } from "react-redux"; import { useParams } from "react-router-dom"; import { HomeBreadcrumbType, HomeLayout } from "./HomeLayout"; -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; +import { useDebouncedValue } from "util/hooks"; import {ApplicationCategoriesEnum, ApplicationMeta, FolderMeta} from "../../constants/applicationConstants"; import { buildFolderUrl } from "../../constants/routesURL"; import { folderElementsSelector, foldersSelector } from "../../redux/selectors/folderSelector"; @@ -100,13 +101,12 @@ export function FolderView() { }, [searchValues] ); - useEffect(()=> { - const timer = setTimeout(() => { - if (searchValue.length > 2 || searchValue === "") - setSearchValues(searchValue) - }, 500); - return () => clearTimeout(timer); - }, [searchValue]) + const debouncedSearchValue = useDebouncedValue(searchValue, 500); + + useEffect(() => { + if (debouncedSearchValue.trim().length > 0 || debouncedSearchValue === "") + setSearchValues(debouncedSearchValue); + }, [debouncedSearchValue]); return ( <> diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/HomeView.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/HomeView.tsx index 3a435a6b8..a49355541 100644 --- a/client/packages/lowcoder/src/pages/ApplicationV2/HomeView.tsx +++ b/client/packages/lowcoder/src/pages/ApplicationV2/HomeView.tsx @@ -3,7 +3,8 @@ import { HomeLayout } from "./HomeLayout"; import { getUser } from "../../redux/selectors/usersSelectors"; import { Helmet } from "react-helmet"; import { trans } from "i18n"; -import {useState, useEffect } from "react"; +import { useState, useEffect } from "react"; +import { useDebouncedValue } from "util/hooks"; import {fetchFolderElements} from "@lowcoder-ee/util/pagination/axios"; import {ApplicationCategoriesEnum, ApplicationMeta, FolderMeta} from "@lowcoder-ee/constants/applicationConstants"; import {ApplicationPaginationType} from "@lowcoder-ee/util/pagination/type"; @@ -53,13 +54,13 @@ export function HomeView() { }, [searchValues] ); - useEffect(()=> { - const timer = setTimeout(() => { - if (searchValue.length > 2 || searchValue === "") - setSearchValues(searchValue) - }, 500); - return () => clearTimeout(timer); - }, [searchValue]) + const debouncedSearchValue = useDebouncedValue(searchValue, 500); + + useEffect(() => { + if (debouncedSearchValue.trim().length > 0 || debouncedSearchValue === "") { + setSearchValues(debouncedSearchValue); + } + }, [debouncedSearchValue]); const user = useSelector(getUser); diff --git a/client/packages/lowcoder/src/pages/ApplicationV2/TrashView.tsx b/client/packages/lowcoder/src/pages/ApplicationV2/TrashView.tsx index 410a2632f..3b6e84390 100644 --- a/client/packages/lowcoder/src/pages/ApplicationV2/TrashView.tsx +++ b/client/packages/lowcoder/src/pages/ApplicationV2/TrashView.tsx @@ -1,6 +1,7 @@ import { HomeLayout } from "./HomeLayout"; import { TRASH_URL } from "../../constants/routesURL"; -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; +import { useDebouncedValue } from "util/hooks"; import { trans } from "../../i18n"; import { Helmet } from "react-helmet"; import {fetchApplicationElements} from "@lowcoder-ee/util/pagination/axios"; @@ -46,14 +47,13 @@ export function TrashView() { }, [searchValues] ); - //debouncing - useEffect(()=> { - const timer = setTimeout(() => { - if (searchValue.length > 2 || searchValue === "") - setSearchValues(searchValue) - }, 500); - return () => clearTimeout(timer); - }, [searchValue]) + const debouncedSearchValue = useDebouncedValue(searchValue, 500); + + useEffect(() => { + if (debouncedSearchValue.trim().length > 0 || debouncedSearchValue === "") { + setSearchValues(debouncedSearchValue); + } + }, [debouncedSearchValue]); return ( <> diff --git a/client/packages/lowcoder/src/pages/datasource/datasourceList.tsx b/client/packages/lowcoder/src/pages/datasource/datasourceList.tsx index 61eb621b2..cc83e64e6 100644 --- a/client/packages/lowcoder/src/pages/datasource/datasourceList.tsx +++ b/client/packages/lowcoder/src/pages/datasource/datasourceList.tsx @@ -1,6 +1,7 @@ import styled from "styled-components"; import { EditPopover, PointIcon, Search, TacoButton } from "lowcoder-design"; -import {useEffect, useState} from "react"; +import { useState, useEffect } from "react"; +import { useDebouncedValue } from "util/hooks"; import { useDispatch, useSelector } from "react-redux"; import { getDataSourceTypesMap } from "../../redux/selectors/datasourceSelectors"; import { deleteDatasource } from "../../redux/reduxActions/datasourceActions"; @@ -124,13 +125,13 @@ export const DatasourceList = () => { const [pageSize, setPageSize] = useState(10); const [paginationLoading, setPaginationLoading] = useState(false); - useEffect(()=> { - const timer = setTimeout(() => { - if (searchValue.length > 2 || searchValue === "") - setSearchValues(searchValue) - }, 500); - return () => clearTimeout(timer); - }, [searchValue]) + const debouncedSearchValue = useDebouncedValue(searchValue, 500); + + useEffect(() => { + if (debouncedSearchValue.trim().length > 0 || debouncedSearchValue === "") { + setSearchValues(debouncedSearchValue); + } + }, [debouncedSearchValue]); useEffect( () => { setPaginationLoading(true); diff --git a/client/packages/lowcoder/src/pages/queryLibrary/LeftNav.tsx b/client/packages/lowcoder/src/pages/queryLibrary/LeftNav.tsx index 84bdade67..6df81dd6b 100644 --- a/client/packages/lowcoder/src/pages/queryLibrary/LeftNav.tsx +++ b/client/packages/lowcoder/src/pages/queryLibrary/LeftNav.tsx @@ -1,4 +1,5 @@ -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; +import { useDebouncedValue } from "util/hooks"; import styled, { css } from "styled-components"; import { BluePlusIcon, @@ -174,14 +175,13 @@ export const LeftNav = (props: { const [searchValue, setSearchValue] = useState(""); const datasourceTypes = useSelector(getDataSourceTypesMap); - useEffect(()=> { - const timer = setTimeout(() => { - if (searchValue.length > 2 || searchValue === "") - setSearchValues(searchValue) - }, 500); - return () => clearTimeout(timer); - }, [searchValue]) + const debouncedSearchValue = useDebouncedValue(searchValue, 500); + useEffect(() => { + if (debouncedSearchValue.trim().length > 0 || debouncedSearchValue === "") { + setSearchValues(debouncedSearchValue); + } + }, [debouncedSearchValue]); return ( diff --git a/client/packages/lowcoder/src/util/hooks.ts b/client/packages/lowcoder/src/util/hooks.ts index 9c9b7777c..796ba7eed 100644 --- a/client/packages/lowcoder/src/util/hooks.ts +++ b/client/packages/lowcoder/src/util/hooks.ts @@ -29,6 +29,7 @@ import { constantColors } from "components/colorSelect/colorUtils"; import { AppState } from "@lowcoder-ee/redux/reducers"; import { getOrgUserStats } from "@lowcoder-ee/redux/selectors/orgSelectors"; import { fetchGroupsAction } from "@lowcoder-ee/redux/reduxActions/orgActions"; +import debounce from "lodash/debounce"; export const ForceViewModeContext = React.createContext(false); @@ -282,3 +283,21 @@ export const useOrgUserCount = (orgId: string) => { return userCount; }; + +/** + * Returns a debounced version of the incoming value that only updates + */ +export function useDebouncedValue(value: T, delay = 500): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + const updater = useMemo(() => debounce(setDebouncedValue, delay), [delay]); + + useEffect(() => { + updater(value); + return () => { + updater.cancel(); + }; + }, [value, updater]); + + return debouncedValue; +} From a6eb2a92bff2f8278aebdf64ed59098846fa0ac9 Mon Sep 17 00:00:00 2001 From: FARAN Date: Mon, 21 Jul 2025 23:08:42 +0500 Subject: [PATCH 5/5] [Fix]: #1849 key error --- client/packages/lowcoder/src/comps/controls/codeControl.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/packages/lowcoder/src/comps/controls/codeControl.tsx b/client/packages/lowcoder/src/comps/controls/codeControl.tsx index 2ae75d7a0..7daa097d5 100644 --- a/client/packages/lowcoder/src/comps/controls/codeControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/codeControl.tsx @@ -189,6 +189,7 @@ export function codeControl< const cardContent = params.disableCard ? "" : getCardContent(this.unevaledValue, this.valueAndMsg, codeControlParams); + const { key, ...restParams } = params; return ( {(editorState) => ( @@ -197,7 +198,8 @@ export function codeControl< <>