Skip to content
This repository was archived by the owner on Jul 15, 2025. It is now read-only.

feat: handle instrument change for chart#104

Merged
farabi-deriv merged 1 commit intoderiv-com:masterfrom
vinu-deriv:Vinu/GRWT-5060/chart-integration
Mar 21, 2025
Merged

feat: handle instrument change for chart#104
farabi-deriv merged 1 commit intoderiv-com:masterfrom
vinu-deriv:Vinu/GRWT-5060/chart-integration

Conversation

@vinu-deriv
Copy link
Contributor

@vinu-deriv vinu-deriv commented Mar 21, 2025

Summary by Sourcery

Updates the chart components to handle instrument changes by clearing existing streams, forcing a chart reload, and displaying a loading indicator. This ensures the chart accurately reflects the currently selected instrument.

Enhancements:

  • Improves chart component to handle instrument changes by clearing existing streams and forcing a chart reload.
  • Adds a loading indicator to the chart component to improve user experience during instrument changes.
  • Adds a function to clear all active subscriptions and history cache.
  • Updates the chart components to use the current instrument when requesting ticks or ticks_history.
  • Updates the chart components to explicitly pass the symbol to the SmartChart component.

@devloai
Copy link

devloai bot commented Mar 21, 2025

Unable to perform a code review. You have run out of credits 😔

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 21, 2025

Reviewer's Guide by Sourcery

This pull request introduces changes to handle instrument changes in the chart components. It includes clearing existing streams, forcing chart re-renders, displaying a loading indicator, and modifying API request handlers to use the effective symbol or instrument when requesting ticks or ticks history. A clearChartCache function was also implemented to clear all active subscriptions and history cache.

Sequence diagram for instrument change in TradeChart

sequenceDiagram
  participant TradeChart
  participant tradeStore
  participant SmartChart
  participant ChartAPI

  TradeChart->>tradeStore: instrument changes
  activate TradeChart
  TradeChart->>TradeChart: setIsChartLoading(true)
  TradeChart->>TradeChart: requestForgetStream()
  activate TradeChart
  TradeChart->>ChartAPI: clearChartCache()
  ChartAPI-->>TradeChart: 
  deactivate TradeChart
  TradeChart->>TradeChart: setChartKey(instrument)
  TradeChart->>TradeChart: setTimeout(1.5s)
  TradeChart->>SmartChart: key=chartKey, symbol=instrument
  activate SmartChart
  SmartChart->>ChartAPI: requestAPI(ticks_history: instrument)
  activate ChartAPI
  ChartAPI-->>SmartChart: chart data
  deactivate ChartAPI
  SmartChart-->>TradeChart: chart rendered
  deactivate SmartChart
  TradeChart->>TradeChart: setIsChartLoading(false)
  deactivate TradeChart
Loading

Sequence diagram for instrument change in ContractDetailsChart

sequenceDiagram
  participant ContractDetailsChart
  participant SmartChart
  participant ChartAPI

  ContractDetailsChart->>ContractDetailsChart: effectiveSymbol changes
  activate ContractDetailsChart
  ContractDetailsChart->>ContractDetailsChart: setIsChartLoading(true)
  ContractDetailsChart->>ContractDetailsChart: clearChartCache()
  activate ContractDetailsChart
  ContractDetailsChart->>ChartAPI: clearChartCache()
  ChartAPI-->>ContractDetailsChart: 
  deactivate ContractDetailsChart
  ContractDetailsChart->>ContractDetailsChart: setChartKey(effectiveSymbol)
  ContractDetailsChart->>ContractDetailsChart: setTimeout(1.5s)
  ContractDetailsChart->>SmartChart: key=chartKey, symbol=effectiveSymbol
  activate SmartChart
  SmartChart->>ChartAPI: requestAPI(ticks_history: effectiveSymbol)
  activate ChartAPI
  ChartAPI-->>SmartChart: chart data
  deactivate ChartAPI
  SmartChart-->>ContractDetailsChart: chart rendered
  deactivate SmartChart
  ContractDetailsChart->>ContractDetailsChart: setIsChartLoading(false)
  deactivate ContractDetailsChart
Loading

File-Level Changes

Change Details Files
Added logic to handle instrument changes in the chart components, including clearing existing streams, forcing chart re-renders, and displaying a loading indicator.
  • Added chartKey state variable to force re-render of the SmartChart component when the instrument changes.
  • Added isChartLoading state variable to display a loading indicator while the chart data is being fetched.
  • Implemented a useEffect hook that triggers when the instrument changes, which clears existing streams, updates the chartKey, and sets a timeout to hide the loading indicator.
  • Added a loading indicator overlay to the chart components.
  • Explicitly passed the effectiveSymbol or instrument as the symbol prop to the SmartChart component.
  • Implemented clearChartCache to clear all active subscriptions and history cache.
src/components/ContractDetailsChart/ContractDetailsChart.tsx
src/components/Chart/Chart.tsx
src/api/services/chart/chart-sse.ts
Modified API request handlers to use the effective symbol or instrument when requesting ticks or ticks history.
  • Updated the requestAPI function to use the effectiveSymbol or instrument when the request is for ticks_history.
  • Updated the requestSubscribe function to use the effectiveSymbol or instrument when the request is for ticks or ticks_history.
src/components/ContractDetailsChart/ContractDetailsChart.tsx
src/components/Chart/Chart.tsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @vinu-deriv - I've reviewed your changes - here's some feedback:

Overall Comments:

  • The loading state and forced re-render logic is duplicated in both chart components; consider refactoring into a shared hook.
  • The timeout duration for the loading indicator should be configurable.
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 2 issues found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -300,10 +301,20 @@ export const ContractDetailsChart: React.FC<ContractDetailsChartProps> = ({

// API request handlers
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Reduce duplication in tick replacement logic in API handlers.

Both the requestAPI and requestSubscribe functions are modifying tick-related properties. If similar logic is required in multiple components, consider extracting a helper function to encapsulate the logic for updating tick or ticks_history with the effective symbol. This can improve maintainability and consistency.

const [chartKey, setChartKey] = useState(effectiveSymbol);
const [isChartLoading, setIsChartLoading] = useState(false);

useEffect(() => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Revisit the fixed 1.5s loading timeout in the chart reload effect.

While a 1500ms delay may work in many cases, this hard-coded timeout might not accommodate variable network or rendering delays. If feasible, consider a mechanism to detect when the chart data actually finishes loading so the loading overlay can be removed at the appropriate time.

};
// When effectiveSymbol changes, forget all existing streams and force chart reload
const [chartKey, setChartKey] = useState(effectiveSymbol);
const [isChartLoading, setIsChartLoading] = useState(false);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider creating a custom hook to encapsulate chart reload logic, which simplifies the component and reduces state duplication..

Consider extracting the chart reload logic into its own custom hook to isolate state handling and side effects. This would remove duplicate state and side effect management from your main component and flatten the logic. For example:

// Create a custom hook in a separate file (e.g., useChartReload.js)
import { useState, useEffect } from "react";
import { clearChartCache } from "@/api/services/chart";

export const useChartReload = (effectiveSymbol) => {
  const [chartKey, setChartKey] = useState(effectiveSymbol);
  const [isChartLoading, setIsChartLoading] = useState(false);

  useEffect(() => {
    setIsChartLoading(true);
    clearChartCache();
    setChartKey(effectiveSymbol);
    const loadingTimeout = setTimeout(() => setIsChartLoading(false), 1500);
    return () => clearTimeout(loadingTimeout);
  }, [effectiveSymbol]);

  return { chartKey, isChartLoading };
};

Then in your component, simply use the hook:

import { useChartReload } from "@/hooks/useChartReload";

const YourChartComponent = ({ effectiveSymbol, ...props }) => {
  const { chartKey, isChartLoading } = useChartReload(effectiveSymbol);

  return (
    <div className="relative">
      {isChartLoading && (
        <div className="absolute inset-0 z-10 flex items-center justify-center bg-theme bg-opacity-80 rounded-lg">
          <div className="text-center">
            <div className="inline-block animate-spin rounded-full h-8 w-8 border-4 border-solid border-blue-500 border-r-transparent"></div>
            <p className="mt-4 text-white">Loading chart data...</p>
          </div>
        </div>
      )}
      <SmartChart
        key={chartKey}
        symbol={effectiveSymbol}
        // ...other props
      />
    </div>
  );
};

This refactoring preserves functionality while reducing in-component complexity and duplicate state management.

handleChartForgetStream,
} from "@/api/services/chart";
import { ToolbarWidgets } from "./Components";
import { useTradeStore } from "@/stores/tradeStore";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider extracting the instrument change and chart reload logic into a custom hook to reduce component complexity and improve code reusability

Consider extracting the duplicated instrument change and chart reload logic into a custom hook. This approach lets you consolidate the state and effect logic, making each component that uses it much simpler. For example:

// useChartReload.ts
import { useEffect, useState } from "react";

export function useChartReload(instrument: string, requestForgetStream: () => void, delay = 1500) {
  const [chartKey, setChartKey] = useState(instrument);
  const [isChartLoading, setIsChartLoading] = useState(false);

  useEffect(() => {
    setIsChartLoading(true);
    requestForgetStream();
    setChartKey(instrument);
    const timer = setTimeout(() => setIsChartLoading(false), delay);
    return () => clearTimeout(timer);
  }, [instrument, requestForgetStream, delay]);

  return { chartKey, isChartLoading };
}

Then refactor your component to use the hook:

import { useChartReload } from "@/hooks/useChartReload";

export const TradeChart: React.FC = () => {
  // ... other declarations
  const instrument = useTradeStore((state) => state.instrument);

  // API request handlers
  const requestForgetStream = () => handleChartForgetStream();

  // Use the custom hook for instrument change reload logic
  const { chartKey, isChartLoading } = useChartReload(instrument, requestForgetStream);

  // ... component JSX remains mostly unchanged
  return (
    <div className="flex h-full relative bg-theme border-r text-gray-100">
      {isChartLoading && (
        <div className="absolute inset-0 z-10 flex items-center justify-center bg-theme bg-opacity-80">
          <div className="text-center">
            <div className="inline-block animate-spin rounded-full h-8 w-8 border-4 border-solid border-blue-500 border-r-transparent"></div>
            <p className="mt-4 text-white">Loading chart data...</p>
          </div>
        </div>
      )}
      <Suspense fallback={<div className="flex items-center justify-center h-full w-full">...loading</div>}>
        <SmartChart
          key={chartKey}
          // ... other props
        />
      </Suspense>
    </div>
  );
};

This refactoring reduces complexity in your component while preserving all current functionality.

@farabi-deriv farabi-deriv merged commit 0f2681f into deriv-com:master Mar 21, 2025
1 of 2 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants