From e4b41b1a276a51b1962ded234755e6bcb93ce12a Mon Sep 17 00:00:00 2001 From: Nidhi Tandon <> Date: Sun, 23 May 2021 15:40:48 +0530 Subject: [PATCH] feat: load data based on isLoaded flag --- frontend/src/modules/BaseLayout.tsx | 31 +------------- frontend/src/modules/RouteProvider.tsx | 42 ++++++++++++++++--- .../Traces/TraceCustomVisualizations.tsx | 8 +++- frontend/src/modules/Traces/TraceFilter.tsx | 6 ++- frontend/src/modules/Usage/UsageExplorer.tsx | 7 +++- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/frontend/src/modules/BaseLayout.tsx b/frontend/src/modules/BaseLayout.tsx index 43df370f49..6e3f52769e 100644 --- a/frontend/src/modules/BaseLayout.tsx +++ b/frontend/src/modules/BaseLayout.tsx @@ -13,41 +13,12 @@ interface BaseLayoutProps { children: ReactNode; } -interface RouteObj { - [key: string]: { - route: string; - isLoaded: boolean; - }; -} const BaseLayout: React.FC = ({ children }) => { const location = useLocation(); const { dispatch } = useRoute(); - /* - Create a routes obj with values as - { - SERVICE_MAP: { - route: '/service-map', - isLoaded: false - } - */ - const routes: RouteObj = {}; - Object.keys(ROUTES).map((items) => { - routes[items] = { - route: `${ROUTES[items]}`, - isLoaded: false, - }; - }); - useEffect(() => { - /* - Update the isLoaded property in routes obj - if the route matches the current pathname - */ - Object.keys(ROUTES).map((items) => { - routes[items].isLoaded = routes[items].route === location.pathname; - }); - dispatch({ type: "UPDATE", payload: routes }); + dispatch({ type: "UPDATE_IS_LOADED", payload: location.pathname }); }, [location]); return ( diff --git a/frontend/src/modules/RouteProvider.tsx b/frontend/src/modules/RouteProvider.tsx index 2894e8fe3f..0680e912c8 100644 --- a/frontend/src/modules/RouteProvider.tsx +++ b/frontend/src/modules/RouteProvider.tsx @@ -1,4 +1,5 @@ import React, { useContext, createContext, ReactNode, Dispatch } from "react"; +import ROUTES from "Src/constants/routes"; type State = { [key: string]: { @@ -7,9 +8,13 @@ type State = { }; }; +enum ActionTypes { + UPDATE_IS_LOADED = "UPDATE_IS_LOADED", +} + type Action = { - type: "UPDATE"; - payload: State; + type: ActionTypes; + payload: string; }; interface ContextType { @@ -22,12 +27,28 @@ const RouteContext = createContext(null); interface RouteProviderProps { children: ReactNode; } +interface RouteObj { + [key: string]: { + route: string; + isLoaded: boolean; + }; +} const updateLocation = (state: State, action: Action): State => { - if (action.type === "UPDATE") { + if (action.type === ActionTypes.UPDATE_IS_LOADED) { + /* + Update the isLoaded property in routes obj + if the route matches the current pathname + + Why: Checkout this issue https://github.com/SigNoz/signoz/issues/110 + To avoid calling the api's twice for Date picker, + We will only call once the route is changed + */ + Object.keys(ROUTES).map((items) => { + state[items].isLoaded = state[items].route === action.payload; + }); return { ...state, - ...action.payload, }; } return { @@ -35,8 +56,19 @@ const updateLocation = (state: State, action: Action): State => { }; }; +const getInitialState = () => { + const routes: RouteObj = {}; + Object.keys(ROUTES).map((items) => { + routes[items] = { + route: `${ROUTES[items]}`, + isLoaded: false, + }; + }); + return routes; +}; + const RouteProvider: React.FC = ({ children }) => { - const [state, dispatch] = React.useReducer(updateLocation, {}); + const [state, dispatch] = React.useReducer(updateLocation, getInitialState()); const value = { state, dispatch }; return {children}; }; diff --git a/frontend/src/modules/Traces/TraceCustomVisualizations.tsx b/frontend/src/modules/Traces/TraceCustomVisualizations.tsx index 3c81ad244b..7b26ce4a29 100644 --- a/frontend/src/modules/Traces/TraceCustomVisualizations.tsx +++ b/frontend/src/modules/Traces/TraceCustomVisualizations.tsx @@ -10,6 +10,7 @@ import { GlobalTime, TraceFilters, } from "../../store/actions"; +import { useRoute } from "../RouteProvider"; const { Option } = Select; @@ -81,6 +82,8 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => { const [selectedEntity, setSelectedEntity] = useState("calls"); const [selectedAggOption, setSelectedAggOption] = useState("count"); const [selectedStep, setSelectedStep] = useState("60"); + const { state } = useRoute(); + // Step should be multiples of 60, 60 -> 1 min useEffect(() => { @@ -109,7 +112,10 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => { minTime: props.globalTime.minTime - 15 * 60 * 1000000000, maxTime: props.globalTime.maxTime + 15 * 60 * 1000000000, }; - props.getFilteredTraceMetrics(request_string, plusMinus15); + + if (state.TRACES.isLoaded) { + props.getFilteredTraceMetrics(request_string, plusMinus15); + } }, [selectedEntity, selectedAggOption, props.traceFilters, props.globalTime]); //Custom metrics API called if time, tracefilters, selected entity or agg option changes diff --git a/frontend/src/modules/Traces/TraceFilter.tsx b/frontend/src/modules/Traces/TraceFilter.tsx index 839ef64d12..06e69f6fd0 100644 --- a/frontend/src/modules/Traces/TraceFilter.tsx +++ b/frontend/src/modules/Traces/TraceFilter.tsx @@ -18,6 +18,7 @@ import FormItem from "antd/lib/form/FormItem"; import api, { apiV1 } from "../../api"; import { useLocation } from "react-router-dom"; import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query"; +import { useRoute } from "../RouteProvider"; const { Option } = Select; @@ -45,6 +46,7 @@ const _TraceFilter = (props: TraceFilterProps) => { const [tagKeyOptions, setTagKeyOptions] = useState([]); const location = useLocation(); const urlParams = new URLSearchParams(location.search.split("?")[1]); + const { state } = useRoute(); useEffect(() => { handleApplyFilterForm({ @@ -122,7 +124,9 @@ const _TraceFilter = (props: TraceFilterProps) => { "&tags=" + encodeURIComponent(JSON.stringify(props.traceFilters.tags)); - props.fetchTraces(props.globalTime, request_string); + if (state.TRACES.isLoaded) { + props.fetchTraces(props.globalTime, request_string); + } }, [props.traceFilters, props.globalTime]); useEffect(() => { diff --git a/frontend/src/modules/Usage/UsageExplorer.tsx b/frontend/src/modules/Usage/UsageExplorer.tsx index 3152e12693..1e1675e0db 100644 --- a/frontend/src/modules/Usage/UsageExplorer.tsx +++ b/frontend/src/modules/Usage/UsageExplorer.tsx @@ -13,6 +13,7 @@ import { import { StoreState } from "../../store/reducers"; import moment from "moment"; import { isOnboardingSkipped } from "../../utils/app"; +import { useRoute } from "../RouteProvider"; const { Option } = Select; interface UsageExplorerProps { @@ -56,6 +57,8 @@ const _UsageExplorer = (props: UsageExplorerProps) => { const [selectedInterval, setSelectedInterval] = useState(interval[2]); const [selectedService, setSelectedService] = useState(""); + const { state } = useRoute(); + useEffect(() => { if (selectedTime && selectedInterval) { const maxTime = new Date().getTime() * 1000000; @@ -71,7 +74,9 @@ const _UsageExplorer = (props: UsageExplorerProps) => { }, [selectedTime, selectedInterval, selectedService]); useEffect(() => { - props.getServicesList(props.globalTime); + if (state.USAGE_EXPLORER.isLoaded) { + props.getServicesList(props.globalTime); + } }, []); const data = {