Skip to content

Commit

Permalink
chore: no complex expressions in preact dependency array
Browse files Browse the repository at this point in the history
Related to hto#444
  • Loading branch information
Skaiir committed Jan 11, 2024
1 parent 41cd974 commit 51e983e
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ export default class RepeatRenderManager {
return (
<>
{displayValues.map((value, index) => {
const elementProps = {
const elementProps = useMemo(() => ({
...restProps,
indexes: { ...(indexes || {}), [ repeaterField.id ]: index },
};
indexes: { ...(indexes || {}), [ repeaterField.id ]: index }
}), [ index ]);

const localExpressionContextInfo = useMemo(() => ({
data: parentExpressionContextInfo.data,
Expand Down
2 changes: 1 addition & 1 deletion packages/form-js-viewer/src/render/components/FormField.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function FormField(props) {
if (viewerCommands && initialValue) {
viewerCommands.updateFieldValidation(field, initialValue, indexes);
}
}, [ viewerCommands, field, initialValue, JSON.stringify(indexes) ]);
}, [ viewerCommands, field, initialValue, indexes ]);

const hidden = useCondition(field.conditional && field.conditional.hide || null);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useMemo, useRef, useState } from 'preact/hooks';

import { useService } from '../../hooks';
import { useDeepCompareState, useService } from '../../hooks';
import useOptionsAsync, { LOAD_STATES } from '../../hooks/useOptionsAsync';
import useCleanupMultiSelectValues from '../../hooks/useCleanupMultiSelectValues';
import { useGetLabelCorrelation } from '../../hooks/useGetLabelCorrelation';
Expand Down Expand Up @@ -35,7 +35,7 @@ export default function Taglist(props) {
onBlur,
field,
readonly,
value : values = []
value
} = props;

const {
Expand All @@ -58,6 +58,9 @@ export default function Taglist(props) {
options
} = useOptionsAsync(field);

// ensures we render based on array content instead of reference
const values = useDeepCompareState(value || [], []);

useCleanupMultiSelectValues({
field,
loadState,
Expand All @@ -70,7 +73,6 @@ export default function Taglist(props) {

const hasOptionsLeft = useMemo(() => options.length > values.length, [ options.length, values.length ]);

// Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
const filteredOptions = useMemo(() => {
if (loadState !== LOAD_STATES.LOADED) {
return [];
Expand All @@ -82,7 +84,7 @@ export default function Taglist(props) {
};

return options.filter(isValidFilteredOption);
}, [ filter, options, JSON.stringify(values), loadState ]);
}, [ filter, options, values, loadState ]);


const selectValue = (value) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import CalendarIcon from '../icons/Calendar.svg';
import InputAdorner from './InputAdorner';
import Label from '../../Label';
import { useDeepCompareState } from '../../../hooks';

export default function Datepicker(props) {

Expand All @@ -18,7 +19,7 @@ export default function Datepicker(props) {
required,
disabled,
disallowPassedDates,
date,
date: dateObject,
readonly,
setDate
} = props;
Expand All @@ -30,6 +31,9 @@ export default function Datepicker(props) {
const [ isInputDirty, setIsInputDirty ] = useState(false);
const [ forceFocusCalendar, setForceFocusCalendar ] = useState(false);

// ensures we render based on date value instead of reference
const date = useDeepCompareState(dateObject, null);

// shorts the date value back to the source
useEffect(() => {

Expand All @@ -38,7 +42,7 @@ export default function Datepicker(props) {
flatpickrInstance.setDate(date, true);
setIsInputDirty(false);

}, [ flatpickrInstance, date.toString() ]);
}, [ flatpickrInstance, date ]);

useEffect(() => {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect } from 'preact/hooks';
import { LOAD_STATES } from './useOptionsAsync';
import { hasEqualValue } from '../components/util/sanitizerUtil';
import useDeepCompareState from './useDeepCompareState';

export default function(props) {

Expand All @@ -9,10 +10,12 @@ export default function(props) {
options,
loadState,
onChange,
values
values: valuesArray
} = props;

// Ensures that the values are always a subset of the possible options
const values = useDeepCompareState(valuesArray, []);

// ensures that the values are always a subset of the possible options
useEffect(() => {

if (loadState !== LOAD_STATES.LOADED) {
Expand All @@ -29,6 +32,6 @@ export default function(props) {
});
}

}, [ field, options, onChange, JSON.stringify(values), loadState ]);
}, [ field, options, onChange, values, loadState ]);

}
12 changes: 3 additions & 9 deletions packages/form-js-viewer/src/render/hooks/useDeepCompareState.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from 'preact/hooks';

import usePrevious from './usePrevious';
import isEqual from 'lodash/isEqual';

/**
* A custom hook to manage state changes with deep comparison.
Expand All @@ -18,7 +19,7 @@ export default function useDeepCompareState(value, defaultValue) {

const previous = usePrevious(value, defaultValue, [ value ]);

const changed = !compare(previous, value);
const changed = !isEqual(previous, value);

useEffect(() => {
if (changed) {
Expand All @@ -27,11 +28,4 @@ export default function useDeepCompareState(value, defaultValue) {
}, [ changed, value ]);

return state;

}

// helpers //////////////////////////

function compare(a, b) {
return JSON.stringify(a) === JSON.stringify(b);
}
}

0 comments on commit 51e983e

Please sign in to comment.