Skip to content

Commit 1610ae3

Browse files
authored
fix(apps/frontend-manage): resolve rendering loop that blocked creation of case study elements (#4732)
1 parent 2a64671 commit 1610ae3

9 files changed

Lines changed: 86 additions & 136 deletions

File tree

apps/frontend-manage/src/components/evaluation/hooks/useChartTypeUpdate.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function useChartTypeUpdate({
3232
setChartType(ACTIVE_CHART_TYPES[activeElementType][0].value)
3333
}
3434
}
35+
// eslint-disable-next-line react-hooks/exhaustive-deps
3536
}, [activeInstance, activeElementType])
3637
}
3738

apps/frontend-manage/src/components/evaluation/hooks/useStackInstanceUpdates.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ function useStackInstanceUpdates({
2020
}
2121
})
2222
}
23+
// eslint-disable-next-line react-hooks/exhaustive-deps
2324
}, [activeInstance])
2425
}
2526

apps/frontend-manage/src/components/questions/manipulation/options/CaseStudyCollectionSelection.tsx

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ import {
99
import { useField } from 'formik'
1010
import { useTranslations } from 'next-intl'
1111
import Link from 'next/link'
12-
import { Dispatch, SetStateAction, useMemo, useState } from 'react'
12+
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'
1313
import Select from 'react-select'
1414
import { twMerge } from 'tailwind-merge'
1515
import { ElementFormTypesCaseStudy } from '../types'
1616
import AnswerCollectionInlineEditButton from './AnswerCollectionInlineEditButton'
1717
import CaseStudyCollectionChangeModal from './CaseStudyCollectionChangeModal'
18-
import useAnswerCollectionChangeEffect from './useAnswerCollectionChangeEffect'
1918
import useSelectAnswerCollectionOptions from './useSelectAnswerCollectionOptions'
2019
import useSelectedAnswerEntry from './useSelectedAnswerEntry'
21-
import useSolutionsUpdateItemsChange from './useSolutionsUpdateItemsChange'
2220

2321
function CaseStudyCollectionSelection({
2422
loading,
@@ -73,19 +71,35 @@ function CaseStudyCollectionSelection({
7371
setSelectedItems,
7472
})
7573

76-
// update the selected correct answers if the answer collection changes
77-
useAnswerCollectionChangeEffect({
78-
field: itemsField,
79-
helpers: itemsHelpers,
80-
collectionAnswers,
81-
})
82-
8374
// update the solutions stored on the cases to be consistent with the selected items
84-
useSolutionsUpdateItemsChange({
85-
itemIds: itemsField.value ?? [],
86-
cases: casesField.value,
87-
casesHelpers,
88-
})
75+
useEffect(() => {
76+
// map over the cases and remove any solutions that do not belong to one of the selected items
77+
const newCases = casesField.value?.map((caseItem) => {
78+
// if no solutions are set, skip this case
79+
if (!('solutions' in caseItem) || !caseItem.solutions) {
80+
return caseItem
81+
}
82+
83+
// filter out all solution entries that do not belong to one of the selected items
84+
const newSolutions = Object.fromEntries(
85+
Object.entries(caseItem.solutions).filter(([itemIdString]) =>
86+
(itemsField.value ?? []).includes(
87+
parseInt(itemIdString.split('-')[1])
88+
)
89+
)
90+
)
91+
92+
return {
93+
...caseItem,
94+
solutions: newSolutions,
95+
}
96+
})
97+
98+
// update the cases field with the new cases
99+
casesHelpers.setValue(newCases)
100+
101+
// eslint-disable-next-line react-hooks/exhaustive-deps
102+
}, [itemsField.value, casesHelpers])
89103

90104
// locally store the selected answer collection
91105
const selectedCollection = useMemo(() => {

apps/frontend-manage/src/components/questions/manipulation/options/SelectionCollectionOptions.tsx

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ import {
1010
import { useField } from 'formik'
1111
import { useTranslations } from 'next-intl'
1212
import Link from 'next/link'
13-
import { Dispatch, SetStateAction, useMemo } from 'react'
13+
import { Dispatch, SetStateAction, useEffect, useMemo } from 'react'
1414
import Select from 'react-select'
1515
import { twMerge } from 'tailwind-merge'
1616
import { ElementFormTypesSelection } from '../types'
1717
import AnswerCollectionInlineEditButton from './AnswerCollectionInlineEditButton'
18-
import useAnswerCollectionChangeEffect from './useAnswerCollectionChangeEffect'
1918
import useSelectAnswerCollectionOptions from './useSelectAnswerCollectionOptions'
2019
import useSelectedAnswerEntry from './useSelectedAnswerEntry'
2120

@@ -67,11 +66,34 @@ function SelectionCollectionOptions({
6766
})
6867

6968
// udpate the selected correct answers if the answer collection changes
70-
useAnswerCollectionChangeEffect({
71-
field: solutions,
72-
helpers: solutionHelpers,
73-
collectionAnswers,
74-
})
69+
useEffect(() => {
70+
// if no collection answers are available, reset the solutions field
71+
if (
72+
!solutions.value ||
73+
!collectionAnswers ||
74+
collectionAnswers.length === 0
75+
) {
76+
if (solutions.value?.length) {
77+
solutionHelpers.setValue([])
78+
}
79+
return
80+
}
81+
82+
const newFieldValues = solutions.value.filter((id) =>
83+
collectionAnswers.map((entry) => entry.value).includes(id)
84+
)
85+
86+
// if the existing solutions and the new ones are not the same, update the solutions field
87+
if (
88+
solutions.value.length !== newFieldValues.length ||
89+
solutions.value.some((id) => !newFieldValues.includes(id))
90+
) {
91+
solutionHelpers.setValue(newFieldValues)
92+
}
93+
94+
// do not add value as a dependency --> rendering loop! - updates only on collection change desired
95+
// eslint-disable-next-line react-hooks/exhaustive-deps
96+
}, [collectionAnswers])
7597

7698
// locally store the selected answer collection
7799
const selectedCollection = useMemo(() => {

apps/frontend-manage/src/components/questions/manipulation/options/SelectionManualItemCreation.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import {
66
} from '@uzh-bf/design-system'
77
import { useField } from 'formik'
88
import { useTranslations } from 'next-intl'
9-
import { Dispatch, SetStateAction } from 'react'
9+
import { Dispatch, SetStateAction, useEffect } from 'react'
1010
import Select from 'react-select'
1111
import Creatable from 'react-select/creatable'
1212
import { ElementFormTypesSelection } from '../types'
1313
import useSelectedAnswerEntry from './useSelectedAnswerEntry'
14-
import useSelectionItemsChangeEffect from './useSelectionItemsChangeEffect'
1514

1615
interface SelectionManualItemCreationProps {
1716
inputsDisabled?: boolean
@@ -48,11 +47,30 @@ function SelectionManualItemCreation({
4847
})
4948

5049
// make sure that only valid elements are stored as correct answers (-> on item removal, the item should also be removed from the correct answers)
51-
useSelectionItemsChangeEffect({
52-
items,
53-
solutions,
54-
solutionHelpers,
55-
})
50+
useEffect(() => {
51+
// if no items are available, reset the solution field
52+
if (!solutions.value || !items.value || items.value.length === 0) {
53+
if (solutions.value?.length) {
54+
solutionHelpers.setValue([])
55+
}
56+
return
57+
}
58+
59+
const newFieldValues = solutions.value.filter((id) =>
60+
items.value!.map((item) => item.id).includes(id)
61+
)
62+
63+
// if the existing solutions and the new ones are not the same, update the solutions field
64+
if (
65+
solutions.value.length !== newFieldValues.length ||
66+
solutions.value.some((id) => !newFieldValues.includes(id))
67+
) {
68+
solutionHelpers.setValue(newFieldValues)
69+
}
70+
71+
// do not add value as a dependency --> rendering loop! - updates only on collection change desired
72+
// eslint-disable-next-line react-hooks/exhaustive-deps
73+
}, [items.value])
5674

5775
return (
5876
<div className="flex w-full flex-col">

apps/frontend-manage/src/components/questions/manipulation/options/useAnswerCollectionChangeEffect.ts

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

apps/frontend-manage/src/components/questions/manipulation/options/useSelectionItemsChangeEffect.ts

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

apps/frontend-manage/src/components/questions/manipulation/options/useSolutionsUpdateItemsChange.ts

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

apps/frontend-pwa/src/components/hooks/useRemainingInstances.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function useRemainingInstances({
4747
}
4848
}
4949
exec()
50+
// eslint-disable-next-line react-hooks/exhaustive-deps
5051
}, [quizId, instances, execution])
5152
}
5253

0 commit comments

Comments
 (0)