Skip to content

Commit ce2952a

Browse files
authored
Merge pull request #38 from tiqi-group/refactor/extract-use-experiments-hook
Refactor: extract useExperiments hook
2 parents 2e78fc5 + f7ede26 commit ce2952a

File tree

6 files changed

+62
-28
lines changed

6 files changed

+62
-28
lines changed

frontend/src/App.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@ import { Outlet } from "react-router";
55
import { ReactRouterAppProvider } from "@toolpad/core/react-router";
66
import type { Navigation } from "@toolpad/core/AppProvider";
77
import { NotificationsProvider } from "@toolpad/core/useNotifications";
8-
import { useEffect, useReducer, useState } from "react";
9-
import { runMethod } from "./socket";
10-
import { deserialize } from "./utils/deserializer";
11-
import { SerializedObject } from "./types/SerializedObject";
8+
import { useReducer } from "react";
129
import { ExperimentsContext } from "./contexts/ExperimentsContext";
13-
import { ExperimentDict } from "./types/ExperimentMetadata";
1410
import { SvgIcon } from "@mui/material";
1511
import SettingsIcon from "@mui/icons-material/Settings";
1612
import { ParameterDisplayGroupsContext } from "./contexts/ParameterDisplayGroupsContext";
@@ -23,6 +19,7 @@ import { DeviceStateContext, deviceStateReducer } from "./contexts/DeviceStateCo
2319
import logo from "./assets/logo.png";
2420
import { useParameterStore } from "./hooks/useParameterStore";
2521
import { useParameterDisplayGroups } from "./hooks/useParameterDisplayGroups";
22+
import { useExperiments } from "./hooks/useExperiments";
2623

2724
const NAVIGATION: Navigation = [
2825
{
@@ -76,21 +73,16 @@ export const BRANDING = {
7673
};
7774

7875
export default function App() {
79-
const [experiments, setExperiments] = useState<ExperimentDict>({});
8076
const [scheduledJobs, schedulerDispatch] = useReducer(reducer, {});
8177
const [deviceInfo, deviceInfoDispatch] = useReducer(deviceInfoReducer, {});
8278
const [deviceStates, deviceStateDispatch] = useReducer(deviceStateReducer, null);
8379
const parameterStore = useParameterStore();
8480
const { parameterDisplayGroups, parameterNamespaceToDisplayGroups } =
8581
useParameterDisplayGroups();
82+
const experiments = useExperiments();
8683

8784
useJobsSync(schedulerDispatch);
8885
useDevicesSync(deviceStateDispatch, deviceInfoDispatch);
89-
useEffect(() => {
90-
runMethod("experiments.get_experiments", [], {}, (ack) => {
91-
setExperiments(deserialize(ack as SerializedObject) as ExperimentDict);
92-
});
93-
}, []);
9486

9587
return (
9688
<ReactRouterAppProvider navigation={NAVIGATION} branding={BRANDING}>

frontend/src/components/parameterComponents/ParameterNumberComponent.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ export const ParameterNumberComponent = React.memo(
5858
[setError, id],
5959
);
6060

61-
console.log("something changed");
6261
return (
6362
<Input
6463
id={id}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { useEffect, useState, useCallback } from "react";
2+
import { runMethod, socket } from "../socket";
3+
import { deserialize } from "../utils/deserializer";
4+
import { SerializedObject } from "../types/SerializedObject";
5+
import { ExperimentDict } from "../types/ExperimentMetadata";
6+
7+
/**
8+
* React hook that provides access to experiment metadata.
9+
*
10+
* This hook:
11+
* - Fetches the full set of experiments from the backend using
12+
* `experiments.get_experiments`.
13+
* - Subscribes to `experiments.update` socket events to refresh data
14+
* when the backend notifies of changes.
15+
* - Cleans up the socket listener on unmount.
16+
*
17+
* @returns The current experiment metadata as an ExperimentDict.
18+
*/
19+
export function useExperiments(): ExperimentDict {
20+
const [experiments, setExperiments] = useState<ExperimentDict>({});
21+
22+
const fetchExperiments = useCallback(() => {
23+
runMethod("experiments.get_experiments", [], {}, (ack) => {
24+
setExperiments(deserialize(ack as SerializedObject) as ExperimentDict);
25+
});
26+
}, []);
27+
28+
useEffect(() => {
29+
fetchExperiments();
30+
socket.on("experiments.update", fetchExperiments);
31+
32+
return () => {
33+
socket.off("experiments.update", fetchExperiments);
34+
};
35+
}, [fetchExperiments]);
36+
37+
return experiments;
38+
}

src/icon/server/api/experiments_controller.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from icon.server.api.models.experiment_dict import (
66
ExperimentDict,
77
)
8+
from icon.server.api.parameters_controller import get_added_removed_and_updated_keys
89
from icon.server.web_server.socketio_emit_queue import emit_queue
910

1011
logger = logging.getLogger(__name__)
@@ -21,11 +22,15 @@ def get_experiments(self) -> ExperimentDict:
2122
def _update_experiment_metadata(self, new_experiments: ExperimentDict) -> None:
2223
logger.debug("Updating experiment metadata...")
2324

25+
added_exps, removes_exps, updated_exps = get_added_removed_and_updated_keys(
26+
self._experiments, new_experiments
27+
)
2428
self._experiments = new_experiments
2529

26-
emit_queue.put(
27-
{
28-
"event": "experiments.update",
29-
"data": new_experiments,
30-
}
31-
)
30+
if added_exps or removes_exps or updated_exps:
31+
emit_queue.put(
32+
{
33+
"event": "experiments.update",
34+
"data": new_experiments,
35+
}
36+
)

0 commit comments

Comments
 (0)