Skip to content

Commit 0426cc3

Browse files
committed
refactor: Use Zustand for state management (metadata panel)
1 parent f1d93f9 commit 0426cc3

1 file changed

Lines changed: 51 additions & 76 deletions

File tree

app/components/metadata-panel.tsx

Lines changed: 51 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import parse from "autosuggest-highlight/parse";
1818
import clsx from "clsx";
1919
import { AnimatePresence, Transition } from "framer-motion";
2020
import React, { useState } from "react";
21+
import create from "zustand";
22+
import shallow from "zustand/shallow";
2123

2224
import { BackButton, DataSource } from "@/configurator";
2325
import { DataSetMetadata } from "@/configurator/components/dataset-metadata";
@@ -31,57 +33,35 @@ import useEvent from "@/utils/use-event";
3133

3234
import Flex from "./flex";
3335

34-
type Section = "general" | "data";
36+
type MetadataPanelSection = "general" | "data";
3537

36-
type State = {
38+
type MetadataPanelState = {
3739
open: boolean;
3840
toggle: () => void;
39-
activeSection: Section;
40-
setActiveSection: (d: Section) => void;
41+
activeSection: MetadataPanelSection;
42+
setActiveSection: (d: MetadataPanelSection) => void;
4143
selectedDimension: DimensionMetadataFragment | undefined;
42-
setSelectedDimension: (d: DimensionMetadataFragment | undefined) => void;
44+
setSelectedDimension: (d: DimensionMetadataFragment) => void;
4345
clearSelectedDimension: () => void;
4446
};
4547

46-
const Context = React.createContext<State | undefined>(undefined);
47-
48-
export const ContextProvider = ({
49-
children,
50-
}: {
51-
children: React.ReactNode;
52-
}) => {
53-
const [open, setOpen] = React.useState(false);
54-
const [activeSection, setActiveSection] = React.useState<Section>("general");
55-
const [selectedDimension, setSelectedDimension] = React.useState<
56-
DimensionMetadataFragment | undefined
57-
>(undefined);
58-
59-
const ctx: State = React.useMemo(() => {
60-
return {
61-
open,
62-
toggle: () => setOpen(!open),
63-
activeSection,
64-
setActiveSection,
65-
selectedDimension,
66-
setSelectedDimension,
67-
clearSelectedDimension: () => setSelectedDimension(undefined),
68-
};
69-
}, [open, activeSection, selectedDimension]);
70-
71-
return <Context.Provider value={ctx}>{children}</Context.Provider>;
72-
};
73-
74-
export const useContext = () => {
75-
const ctx = React.useContext(Context);
76-
77-
if (ctx === undefined) {
78-
throw Error(
79-
"You need to wrap your component in <ContextProvider /> to useContext()"
80-
);
81-
}
82-
83-
return ctx;
84-
};
48+
export const useMetadataPanelStore = create<MetadataPanelState>((set, get) => ({
49+
open: false,
50+
toggle: () => {
51+
set({ open: !get().open });
52+
},
53+
activeSection: "general",
54+
setActiveSection: (d: MetadataPanelSection) => {
55+
set({ activeSection: d });
56+
},
57+
selectedDimension: undefined,
58+
setSelectedDimension: (d: DimensionMetadataFragment) => {
59+
set({ selectedDimension: d });
60+
},
61+
clearSelectedDimension: () => {
62+
set({ selectedDimension: undefined });
63+
},
64+
}));
8565

8666
const useDrawerStyles = makeStyles<Theme, { top: number }>((theme) => {
8767
return {
@@ -163,32 +143,6 @@ const useOtherStyles = makeStyles<Theme>((theme) => {
163143
};
164144
});
165145

166-
export const MetadataPanel = ({
167-
datasetIri,
168-
dataSource,
169-
dimensions,
170-
container,
171-
top,
172-
}: {
173-
datasetIri: string;
174-
dataSource: DataSource;
175-
dimensions: DimensionMetadataFragment[];
176-
container?: HTMLDivElement | null;
177-
top?: number;
178-
}) => {
179-
return (
180-
<ContextProvider>
181-
<PanelInner
182-
datasetIri={datasetIri}
183-
dataSource={dataSource}
184-
dimensions={dimensions}
185-
container={container}
186-
top={top}
187-
/>
188-
</ContextProvider>
189-
);
190-
};
191-
192146
const animationProps: Transition = {
193147
transition: {
194148
duration: 0.2,
@@ -204,7 +158,7 @@ const animationProps: Transition = {
204158
},
205159
};
206160

207-
const PanelInner = ({
161+
export const MetadataPanel = ({
208162
datasetIri,
209163
dataSource,
210164
dimensions,
@@ -214,12 +168,21 @@ const PanelInner = ({
214168
datasetIri: string;
215169
dataSource: DataSource;
216170
dimensions: DimensionMetadataFragment[];
217-
container: HTMLDivElement | null | undefined;
171+
container?: HTMLDivElement | null;
218172
top?: number;
219173
}) => {
220174
const drawerClasses = useDrawerStyles({ top });
221175
const otherClasses = useOtherStyles();
222-
const { open, toggle, activeSection, setActiveSection } = useContext();
176+
const { open, toggle, activeSection, setActiveSection } =
177+
useMetadataPanelStore(
178+
(state) => ({
179+
open: state.open,
180+
toggle: state.toggle,
181+
activeSection: state.activeSection,
182+
setActiveSection: state.setActiveSection,
183+
}),
184+
shallow
185+
);
223186
const handleToggle = useEvent(() => {
224187
toggle();
225188
});
@@ -342,7 +305,14 @@ const TabPanelData = ({
342305
}) => {
343306
const classes = useOtherStyles();
344307
const { selectedDimension, setSelectedDimension, clearSelectedDimension } =
345-
useContext();
308+
useMetadataPanelStore(
309+
(state) => ({
310+
selectedDimension: state.selectedDimension,
311+
setSelectedDimension: state.setSelectedDimension,
312+
clearSelectedDimension: state.clearSelectedDimension,
313+
}),
314+
shallow
315+
);
346316
const [inputValue, setInputValue] = useState("");
347317

348318
const options = React.useMemo(() => {
@@ -373,7 +343,7 @@ const TabPanelData = ({
373343
<Autocomplete
374344
className={classes.search}
375345
disablePortal
376-
onChange={(_, v) => setSelectedDimension(v?.value)}
346+
onChange={(_, v) => v && setSelectedDimension(v.value)}
377347
inputValue={inputValue}
378348
onInputChange={(_, v) => setInputValue(v.toLowerCase())}
379349
options={options}
@@ -443,7 +413,12 @@ const TabPanelDataDimension = ({
443413
expandable: boolean;
444414
}) => {
445415
const classes = useOtherStyles();
446-
const { setSelectedDimension } = useContext();
416+
const { setSelectedDimension } = useMetadataPanelStore(
417+
(state) => ({
418+
setSelectedDimension: state.setSelectedDimension,
419+
}),
420+
shallow
421+
);
447422
const { description, showExpandButton } = React.useMemo(() => {
448423
if (expandable && dim.description && dim.description.length > 180) {
449424
return {

0 commit comments

Comments
 (0)