diff --git a/optuna_dashboard/ts/components/GraphRank.tsx b/optuna_dashboard/ts/components/GraphRank.tsx
index d1ce9d19..b288874c 100644
--- a/optuna_dashboard/ts/components/GraphRank.tsx
+++ b/optuna_dashboard/ts/components/GraphRank.tsx
@@ -14,8 +14,9 @@ import {
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
import { getAxisInfo, makeHovertext } from "../graphUtil"
import { useMergedUnionSearchSpace } from "../searchSpace"
-import { getPlotAPI, PlotType } from "../apiClient"
+import { PlotType } from "../apiClient"
import { useBackendRender } from "../state"
+import { usePlot } from "../hooks/usePlot"
const plotDomId = "graph-rank"
@@ -47,18 +48,23 @@ const GraphRankBackend: FC<{
const studyId = study?.id
const numCompletedTrials =
study?.trials.filter((t) => t.state === "Complete").length || 0
+ const { data, layout, error } = usePlot({
+ numCompletedTrials,
+ studyId,
+ plotType: PlotType.Rank,
+ })
+
useEffect(() => {
- if (studyId === undefined) {
- return
+ if (data && layout) {
+ plotly.react(plotDomId, data, layout)
}
- getPlotAPI(studyId, PlotType.Rank)
- .then(({ data, layout }) => {
- plotly.react(plotDomId, data, layout)
- })
- .catch((err) => {
- console.error(err)
- })
- }, [studyId, numCompletedTrials])
+ }, [data, layout])
+ useEffect(() => {
+ if (error) {
+ console.error(error)
+ }
+ }, [error])
+
return
}
diff --git a/optuna_dashboard/ts/hooks/useParamImportance.ts b/optuna_dashboard/ts/hooks/useParamImportance.ts
index 8b145b2b..3728320f 100644
--- a/optuna_dashboard/ts/hooks/useParamImportance.ts
+++ b/optuna_dashboard/ts/hooks/useParamImportance.ts
@@ -10,7 +10,10 @@ export const useParamImportance = ({
}: { numCompletedTrials: number; studyId: number }) => {
const { enqueueSnackbar } = useSnackbar()
- const { data, isLoading, error } = useQuery>({
+ const { data, isLoading, error } = useQuery<
+ ParamImportance[][],
+ AxiosError<{ reason: string }>
+ >({
queryKey: ["paramImportance", studyId, numCompletedTrials],
queryFn: () => getParamImportances(studyId),
staleTime: Infinity,
diff --git a/optuna_dashboard/ts/hooks/usePlot.ts b/optuna_dashboard/ts/hooks/usePlot.ts
new file mode 100644
index 00000000..3c3036ad
--- /dev/null
+++ b/optuna_dashboard/ts/hooks/usePlot.ts
@@ -0,0 +1,37 @@
+import * as plotly from "plotly.js-dist-min"
+import { useQuery } from "@tanstack/react-query"
+import { AxiosError } from "axios"
+import { PlotType, getPlotAPI } from "../apiClient"
+
+export const usePlot = ({
+ numCompletedTrials,
+ studyId,
+ plotType,
+}: {
+ numCompletedTrials: number
+ studyId: number | undefined
+ plotType: PlotType
+}) => {
+ const { data, isLoading, error } = useQuery<
+ { data: plotly.Data[]; layout: plotly.Layout },
+ AxiosError
+ >({
+ enabled: studyId !== undefined,
+ queryKey: ["plot", studyId, numCompletedTrials],
+ queryFn: () => {
+ if (studyId === undefined) {
+ return Promise.reject(new Error("Invalid studyId"))
+ }
+ return getPlotAPI(studyId, plotType)
+ },
+ staleTime: Infinity,
+ gcTime: Infinity,
+ })
+
+ return {
+ data: data?.data,
+ layout: data?.layout,
+ isLoading,
+ error,
+ }
+}