Skip to content

Commit 9ed8295

Browse files
olemartinorgOle Martin Handeland
andauthored
Refactor: Making TaskStore a regular context (#3732)
* Simplifying TaskStore by just using it as a normal context instead of using zustand. It is only really used to override things, and the pattern we used to wait until things were set in zustand clearly indicated this was the wrong approach. * Renaming file, renaming dataElementId -> dataModelElementId * Depth is never read(!) * Suggestions from coderabbit in review * I found another issue. The useLayoutSetId() hook was overly complicated, and did much of the same stuff that useCurrentLayoutSetId() already did. The main difference was the taskId source, where useLayoutSetId() preferred the one from the URL, so I renamed it to reflect that. * Fixing import --------- Co-authored-by: Ole Martin Handeland <[email protected]>
1 parent 8556c9a commit 9ed8295

File tree

23 files changed

+256
-375
lines changed

23 files changed

+256
-375
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React, { createContext, useContext } from 'react';
2+
import type { PropsWithChildren } from 'react';
3+
4+
interface TaskOverridesContext {
5+
taskId?: string;
6+
dataModelType?: string;
7+
dataModelElementId?: string;
8+
layoutSetId?: string;
9+
}
10+
11+
const Context = createContext<TaskOverridesContext>({});
12+
Context.displayName = 'TaskOverridesContext';
13+
14+
type Props = PropsWithChildren & TaskOverridesContext;
15+
export function TaskOverrides({ children, ...overrides }: Props) {
16+
const parentContext = useContext(Context);
17+
18+
return (
19+
<Context.Provider
20+
value={{
21+
taskId: overrides.taskId ?? parentContext.taskId,
22+
dataModelType: overrides.dataModelType ?? parentContext.dataModelType,
23+
dataModelElementId: overrides.dataModelElementId ?? parentContext.dataModelElementId,
24+
layoutSetId: overrides.layoutSetId ?? parentContext.layoutSetId,
25+
}}
26+
>
27+
{children}
28+
</Context.Provider>
29+
);
30+
}
31+
32+
export const useTaskOverrides = () => useContext(Context);

src/core/contexts/taskStoreContext.tsx

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/features/attachments/StoreAttachmentsInNode.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
22

33
import deepEqual from 'fast-deep-equal';
44

5-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
5+
import { useTaskOverrides } from 'src/core/contexts/TaskOverrides';
66
import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
77
import { isAttachmentUploaded } from 'src/features/attachments/index';
88
import { DEFAULT_DEBOUNCE_TIMEOUT } from 'src/features/formData/types';
@@ -89,15 +89,14 @@ function useNodeAttachments(): AttachmentRecord {
8989
const { indexedId, baseId } = parent;
9090
const nodeData = useFormDataFor(baseId) as IComponentFormData<CompWithBehavior<'canHaveAttachments'>>;
9191

92-
const overriddenTaskId = useTaskStore((state) => state.overriddenTaskId);
92+
const overriddenTaskId = useTaskOverrides()?.taskId;
9393

9494
const application = useApplicationMetadata();
9595
const currentTask = useProcessQuery().data?.currentTask?.elementId;
9696
const data = useInstanceDataElements(baseId);
9797

9898
const mappedAttachments = useMemoDeepEqual(() => {
99-
const taskId = overriddenTaskId ? overriddenTaskId : currentTask;
100-
99+
const taskId = overriddenTaskId ?? currentTask;
101100
return mapAttachments(indexedId, baseId, data, application, taskId, nodeData);
102101
}, [indexedId, baseId, data, application, currentTask, nodeData, overriddenTaskId]);
103102

src/features/datamodel/DataModelsProvider.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import deepEqual from 'fast-deep-equal';
66
import { createStore } from 'zustand';
77
import type { JSONSchema7 } from 'json-schema';
88

9-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
9+
import { useTaskOverrides } from 'src/core/contexts/TaskOverrides';
1010
import { createZustandContext } from 'src/core/contexts/zustandContext';
1111
import { DisplayError } from 'src/core/errorHandling/DisplayError';
1212
import { Loader } from 'src/core/loading/Loader';
@@ -170,8 +170,9 @@ function DataModelsLoader() {
170170
const layoutSetId = useCurrentLayoutSetId();
171171

172172
// Subform
173-
const overriddenDataElementId = useTaskStore((state) => state.overriddenDataElementId);
174-
const overriddenDataType = useTaskStore((state) => state.overriddenDataModelType);
173+
const overrides = useTaskOverrides();
174+
const overriddenDataElementId = overrides?.dataModelElementId;
175+
const overriddenDataType = overrides?.dataModelType;
175176

176177
// Find all data types referenced in dataModelBindings in the layout
177178
useEffect(() => {

src/features/datamodel/useBindingSchema.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useCallback, useMemo } from 'react';
22

33
import type { JSONSchema7 } from 'json-schema';
44

5-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
5+
import { useTaskOverrides } from 'src/core/contexts/TaskOverrides';
66
import { useApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
77
import {
88
getCurrentDataTypeForApplication,
@@ -34,7 +34,7 @@ export function useCurrentDataModelDataElementId() {
3434
const layoutSets = useLayoutSets();
3535
const taskId = useProcessTaskId();
3636

37-
const overriddenDataElementId = useTaskStore((s) => s.overriddenDataElementId);
37+
const overriddenDataElementId = useTaskOverrides()?.dataModelElementId;
3838

3939
// Instance data elements will update often (after each save), so we have to use a selector to make
4040
// sure components don't re-render too often.
@@ -130,7 +130,7 @@ export function useDataModelUrl({ dataType, dataElementId, language, prefillFrom
130130
}
131131

132132
export function useCurrentDataModelName() {
133-
const overriddenDataModelType = useTaskStore((state) => state.overriddenDataModelType);
133+
const overriddenDataModelType = useTaskOverrides()?.dataModelType;
134134

135135
const application = useApplicationMetadata();
136136
const layoutSets = useLayoutSets();

src/features/devtools/components/LayoutInspector/LayoutInspector.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import { LayoutInspectorItem } from 'src/features/devtools/components/LayoutInsp
1010
import { SplitView } from 'src/features/devtools/components/SplitView/SplitView';
1111
import { useDevToolsStore } from 'src/features/devtools/data/DevToolsStore';
1212
import { useLayoutValidationForPage } from 'src/features/devtools/layoutValidation/useLayoutValidation';
13-
import { useLayouts, useLayoutSetId } from 'src/features/form/layout/LayoutsContext';
13+
import { useLayouts } from 'src/features/form/layout/LayoutsContext';
14+
import { useLayoutSetIdFromUrl } from 'src/features/form/layoutSets/useCurrentLayoutSet';
1415
import { useCurrentView } from 'src/hooks/useNavigatePage';
1516
import { parseAndCleanText } from 'src/language/sharedLanguage';
1617
import type { LayoutContextValue } from 'src/features/form/layout/LayoutsContext';
@@ -20,7 +21,7 @@ export const LayoutInspector = () => {
2021
const setSelectedComponent = useDevToolsStore((state) => state.actions.layoutInspectorSet);
2122
const currentView = useCurrentView();
2223
const layouts = useLayouts();
23-
const currentLayoutSetId = useLayoutSetId();
24+
const currentLayoutSetId = useLayoutSetIdFromUrl();
2425
const [componentProperties, setComponentProperties] = useState<string | null>(null);
2526
const [propertiesHaveChanged, setPropertiesHaveChanged] = useState(false);
2627
const [error, setError] = useState<boolean>(false);

src/features/form/layout/LayoutsContext.tsx

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ import { useAppQueries } from 'src/core/contexts/AppQueriesProvider';
66
import { ContextNotProvided } from 'src/core/contexts/context';
77
import { delayedContext } from 'src/core/contexts/delayedContext';
88
import { createQueryContext } from 'src/core/contexts/queryContext';
9-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
109
import { useCurrentDataModelName } from 'src/features/datamodel/useBindingSchema';
1110
import { cleanLayout } from 'src/features/form/layout/cleanLayout';
1211
import { makeLayoutLookups } from 'src/features/form/layout/makeLayoutLookups';
1312
import { applyLayoutQuirks } from 'src/features/form/layout/quirks';
1413
import { useLayoutSets } from 'src/features/form/layoutSets/LayoutSetsProvider';
15-
import { useCurrentLayoutSetId } from 'src/features/form/layoutSets/useCurrentLayoutSet';
14+
import { useLayoutSetIdFromUrl } from 'src/features/form/layoutSets/useCurrentLayoutSet';
1615
import { useInstanceDataQuery } from 'src/features/instance/InstanceContext';
1716
import { useProcessQuery } from 'src/features/instance/useProcessQuery';
18-
import { useNavigationParam } from 'src/hooks/navigation';
1917
import { makeLikertChildId } from 'src/layout/Likert/Generator/makeLikertChildId';
2018
import type { QueryDefinition } from 'src/core/queries/usePrefetchQuery';
2119
import type { CompExternal, ILayoutCollection, ILayouts } from 'src/layout/layout';
@@ -45,7 +43,7 @@ export function useLayoutQueryDef(
4543

4644
function useLayoutQuery() {
4745
const { data: process } = useProcessQuery();
48-
const currentLayoutSetId = useLayoutSetId();
46+
const currentLayoutSetId = useLayoutSetIdFromUrl();
4947
const defaultDataModel = useCurrentDataModelName() ?? 'unknown';
5048
const hasInstance = !!useInstanceDataQuery().data;
5149

@@ -78,30 +76,6 @@ const { Provider, useCtx, useLaxCtx } = delayedContext(() =>
7876
}),
7977
);
8078

81-
export function useLayoutSetId() {
82-
const layoutSets = useLayoutSets();
83-
const currentProcessLayoutSetId = useCurrentLayoutSetId();
84-
const taskId = useNavigationParam('taskId');
85-
86-
const overriddenLayoutSetId = useTaskStore((state) => state.overriddenLayoutSetId);
87-
88-
if (overriddenLayoutSetId) {
89-
return overriddenLayoutSetId;
90-
}
91-
92-
const layoutSetId =
93-
taskId != null
94-
? layoutSets.find((set) => {
95-
if (set.tasks?.length) {
96-
return set.tasks.includes(taskId);
97-
}
98-
return false;
99-
})?.id
100-
: undefined;
101-
102-
return layoutSetId ?? currentProcessLayoutSetId;
103-
}
104-
10579
export function useDataTypeFromLayoutSet(layoutSetName: string | undefined) {
10680
const layoutSets = useLayoutSets();
10781
return layoutSets.find((set) => set.id === layoutSetName)?.dataType;

src/features/form/layoutSets/useCurrentLayoutSet.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
import { ContextNotProvided } from 'src/core/contexts/context';
2-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
2+
import { useTaskOverrides } from 'src/core/contexts/TaskOverrides';
33
import { useLaxApplicationMetadata } from 'src/features/applicationMetadata/ApplicationMetadataProvider';
44
import { getCurrentLayoutSet } from 'src/features/applicationMetadata/appMetadataUtils';
55
import { useLaxLayoutSets } from 'src/features/form/layoutSets/LayoutSetsProvider';
66
import { useProcessTaskId } from 'src/features/instance/useProcessTaskId';
7+
import { useNavigationParam } from 'src/hooks/navigation';
78

8-
export function useCurrentLayoutSetId() {
9-
return useCurrentLayoutSet()?.id;
9+
/**
10+
* This is a variant that prefers the taskId from the URL. The alternative useCurrentLayoutSetId() and
11+
* useCurrentLayoutSet() will prefer the taskId from the current process state (i.e., where the process is right now,
12+
* not necessarily what the user is looking at right now).
13+
*/
14+
export function useLayoutSetIdFromUrl() {
15+
const taskId = useNavigationParam('taskId');
16+
return useCurrentLayoutSetId(taskId);
1017
}
1118

12-
export function useCurrentLayoutSet() {
19+
export function useCurrentLayoutSetId(taskId?: string) {
20+
return useCurrentLayoutSet(taskId)?.id;
21+
}
22+
23+
export function useCurrentLayoutSet(_taskId?: string) {
1324
const application = useLaxApplicationMetadata();
1425
const layoutSets = useLaxLayoutSets();
15-
const taskId = useProcessTaskId();
16-
const overriddenLayoutSetId = useTaskStore((state) => state.overriddenLayoutSetId);
26+
const processTaskId = useProcessTaskId();
27+
const taskId = _taskId ?? processTaskId;
28+
const overriddenLayoutSetId = useTaskOverrides()?.layoutSetId;
1729

1830
if (application === ContextNotProvided || layoutSets === ContextNotProvided) {
1931
return undefined;

src/features/form/layoutSettings/LayoutSettingsContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { useAppQueries } from 'src/core/contexts/AppQueriesProvider';
77
import { ContextNotProvided } from 'src/core/contexts/context';
88
import { delayedContext } from 'src/core/contexts/delayedContext';
99
import { createQueryContext } from 'src/core/contexts/queryContext';
10-
import { useLayoutSetId } from 'src/features/form/layout/LayoutsContext';
1110
import { useLaxGlobalUISettings } from 'src/features/form/layoutSets/LayoutSetsProvider';
11+
import { useLayoutSetIdFromUrl } from 'src/features/form/layoutSets/useCurrentLayoutSet';
1212
import { useShallowMemo } from 'src/hooks/useShallowMemo';
1313
import type { QueryDefinition } from 'src/core/queries/usePrefetchQuery';
1414
import type { GlobalPageSettings, ILayoutSettings, NavigationPageGroup } from 'src/layout/common.generated';
@@ -23,7 +23,7 @@ export function useLayoutSettingsQueryDef(layoutSetId?: string): QueryDefinition
2323
}
2424

2525
function useLayoutSettingsQuery() {
26-
const layoutSetId = useLayoutSetId();
26+
const layoutSetId = useLayoutSetIdFromUrl();
2727
const query = useQuery(useLayoutSettingsQueryDef(layoutSetId));
2828

2929
useEffect(() => {

src/features/instance/useProcessTaskId.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { useTaskStore } from 'src/core/contexts/taskStoreContext';
1+
import { useTaskOverrides } from 'src/core/contexts/TaskOverrides';
22
import { useProcessQuery } from 'src/features/instance/useProcessQuery';
33
import { useNavigationParam } from 'src/hooks/navigation';
44

55
export function useProcessTaskId() {
6-
const overriddenTaskId = useTaskStore((state) => state.overriddenTaskId);
6+
const overriddenTaskId = useTaskOverrides()?.taskId;
77
const processTaskId = useProcessQuery().data?.currentTask?.elementId;
88
const urlTaskId = useNavigationParam('taskId');
99
return overriddenTaskId ?? processTaskId ?? urlTaskId;

0 commit comments

Comments
 (0)