added debouncing

This commit is contained in:
tomato6966 2024-12-22 00:58:20 +01:00
parent 1edf7cbb23
commit 50a9cdb073
5 changed files with 44 additions and 25 deletions

13
package-lock.json generated
View file

@ -14,6 +14,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"recharts": "^2.12.1",
"use-debounce": "^10.0.4",
"zustand": "^4.5.1"
},
"devDependencies": {
@ -4172,6 +4173,18 @@
"punycode": "^2.1.0"
}
},
"node_modules/use-debounce": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.4.tgz",
"integrity": "sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==",
"license": "MIT",
"engines": {
"node": ">= 16.0.0"
},
"peerDependencies": {
"react": "*"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",

View file

@ -16,6 +16,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"recharts": "^2.12.1",
"use-debounce": "^10.0.4",
"zustand": "^4.5.1"
},
"devDependencies": {

View file

@ -41,7 +41,7 @@ export default function App() {
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8 mb-8 dark:text-gray-300">
<div className="col-span-3">
<PortfolioChart/>
<PortfolioChart />
</div>
<div className="col-span-3 lg:col-span-1">
<InvestmentFormWrapper />

View file

@ -1,5 +1,6 @@
import { Search, X } from "lucide-react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import React, { useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { getHistoricalData, searchAssets } from "../services/yahooFinanceService";
import { usePortfolioStore } from "../store/portfolioStore";
@ -13,26 +14,6 @@ export const AddAssetModal = ({ onClose }: { onClose: () => void }) => {
addAsset: state.addAsset,
dateRange: state.dateRange,
}));
const searchTimeoutRef = useRef<NodeJS.Timeout>();
const debouncedSearch = useCallback((query: string) => {
if (searchTimeoutRef.current) {
clearTimeout(searchTimeoutRef.current);
}
searchTimeoutRef.current = setTimeout(() => {
handleSearch(query);
}, 500);
}, []);
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (searchTimeoutRef.current) {
clearTimeout(searchTimeoutRef.current);
}
};
}, []);
const handleSearch = async (query: string) => {
if (query.length < 2) return;
@ -47,6 +28,8 @@ export const AddAssetModal = ({ onClose }: { onClose: () => void }) => {
}
};
const debouncedSearch = useDebouncedCallback(handleSearch, 750);
const handleAssetSelect = async (asset: Asset) => {
setLoading(true);
try {

View file

@ -4,9 +4,12 @@ import { useCallback, useMemo, useState } from "react";
import {
CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis
} from "recharts";
import { useDebouncedCallback } from "use-debounce";
import { useDarkMode } from "../providers/DarkModeProvider";
import { getHistoricalData } from "../services/yahooFinanceService";
import { usePortfolioStore } from "../store/portfolioStore";
import { DateRange } from "../types";
import { calculatePortfolioValue } from "../utils/calculations/portfolioValue";
import { DateRangePicker } from "./DateRangePicker";
@ -45,12 +48,25 @@ export const PortfolioChart = () => {
const [hideAssets, setHideAssets] = useState(false);
const [hiddenAssets, setHiddenAssets] = useState<Set<string>>(new Set());
const { isDarkMode } = useDarkMode();
const { assets, dateRange, updateDateRange } = usePortfolioStore((state) => ({
const { assets, dateRange, updateDateRange, updateAssetHistoricalData } = usePortfolioStore((state) => ({
assets: state.assets,
dateRange: state.dateRange,
updateDateRange: state.updateDateRange,
updateAssetHistoricalData: state.updateAssetHistoricalData,
}));
const fetchHistoricalData = useCallback(
async (startDate: string, endDate: string) => {
assets.forEach(async (asset) => {
const historicalData = await getHistoricalData(asset.symbol, startDate, endDate);
updateAssetHistoricalData(asset.id, historicalData);
});
}, [assets, updateAssetHistoricalData]);
const debouncedFetchHistoricalData = useDebouncedCallback(fetchHistoricalData, 1500, {
maxWait: 5000,
});
const assetColors: Record<string, string> = useMemo(() => {
const usedColors = new Set<string>();
return assets.reduce((colors, asset) => {
@ -176,14 +192,20 @@ export const PortfolioChart = () => {
);
}, [hideAssets, hiddenAssets, toggleAsset, toggleAllAssets]);
const handleUpdateDateRange = useCallback((newRange: DateRange) => {
updateDateRange(newRange);
debouncedFetchHistoricalData(newRange.startDate, newRange.endDate);
}, [updateDateRange, debouncedFetchHistoricalData]);
const ChartContent = useCallback(() => (
<>
<div className="flex justify-between items-center mb-4">
<DateRangePicker
startDate={dateRange.startDate}
endDate={dateRange.endDate}
onStartDateChange={(date) => updateDateRange({ ...dateRange, startDate: date })}
onEndDateChange={(date) => updateDateRange({ ...dateRange, endDate: date })}
onStartDateChange={(date) => handleUpdateDateRange({ ...dateRange, startDate: date })}
onEndDateChange={(date) => handleUpdateDateRange({ ...dateRange, endDate: date })}
/>
<button
onClick={() => setIsFullscreen(!isFullscreen)}