From 03f6346e9b7979a331510ad18d01547f9c559a4d Mon Sep 17 00:00:00 2001 From: Martin Marosi Date: Thu, 21 Mar 2024 09:11:29 +0100 Subject: [PATCH 1/3] fix(common): useSelect rendering loop --- packages/common/src/use-select/use-select.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/src/use-select/use-select.js b/packages/common/src/use-select/use-select.js index 92c93981f..233edb67c 100644 --- a/packages/common/src/use-select/use-select.js +++ b/packages/common/src/use-select/use-select.js @@ -114,7 +114,7 @@ const useSelect = ({ }, [loadOptionsStr, loadOptionsChangeCounter]); useEffect(() => { - if (state.isInitialLoaded) { + if (!isEqual(state.options, propsOptions) && state.isInitialLoaded) { if (!noValueUpdates && value && !propsOptions.map(({ value }) => value).includes(value)) { onChange(undefined); } From dc745bf9fd0cb68d24edacc1969ee8407cbddbe3 Mon Sep 17 00:00:00 2001 From: Martin Marosi Date: Thu, 21 Mar 2024 09:38:45 +0100 Subject: [PATCH 2/3] fix(common): memoize initial select options value --- packages/common/src/select/select.js | 2 +- packages/common/src/use-select/use-select.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/common/src/select/select.js b/packages/common/src/select/select.js index ae4555364..224b1de55 100644 --- a/packages/common/src/select/select.js +++ b/packages/common/src/select/select.js @@ -12,7 +12,7 @@ const Select = ({ simpleValue = true, isMulti, pluckSingleValue = true, - options: propsOptions = [], + options: propsOptions, loadOptions, loadingMessage, placeholder = 'Choose...', diff --git a/packages/common/src/use-select/use-select.js b/packages/common/src/use-select/use-select.js index 233edb67c..25e9a0e8d 100644 --- a/packages/common/src/use-select/use-select.js +++ b/packages/common/src/use-select/use-select.js @@ -1,4 +1,4 @@ -import { useEffect, useReducer } from 'react'; +import { useEffect, useReducer, useState } from 'react'; import isEqual from 'lodash/isEqual'; @@ -58,7 +58,7 @@ const handleSelectChange = (option, simpleValue, isMulti, onChange, allOptions, const useSelect = ({ loadOptions, optionsTransformer, - options: propsOptions, + options: initialOptions = [], noValueUpdates, onChange, value, @@ -69,9 +69,16 @@ const useSelect = ({ simpleValue, compareValues, }) => { - const [state, originalDispatch] = useReducer(reducer, { optionsTransformer, propsOptions }, init); + const [propsOptions, setPropsCache] = useState(initialOptions); + const [state, originalDispatch] = useReducer(reducer, { optionsTransformer, propsOptions: initialOptions }, init); const dispatch = (action) => originalDispatch({ ...action, optionsTransformer }); + useEffect(() => { + if (!isEqual(initialOptions, propsOptions)) { + setPropsCache(initialOptions); + } + }, [initialOptions]); + const isMounted = useIsMounted(); const updateOptions = () => { From 23a38f543e2e9b6d0d9716fcefbf6b26b41787bc Mon Sep 17 00:00:00 2001 From: Martin Marosi Date: Thu, 21 Mar 2024 09:42:24 +0100 Subject: [PATCH 3/3] fix(common): lift compare values from select promises --- packages/common/src/use-select/reducer.js | 11 ++++------- packages/common/src/use-select/use-select.js | 6 +++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/common/src/use-select/reducer.js b/packages/common/src/use-select/reducer.js index 688fcd51d..458755534 100644 --- a/packages/common/src/use-select/reducer.js +++ b/packages/common/src/use-select/reducer.js @@ -6,7 +6,7 @@ export const init = ({ propsOptions, optionsTransformer }) => ({ ...(optionsTransformer && { originalOptions: propsOptions }), }); -const reducer = (state, { type, payload, options = [], optionsTransformer }) => { +const reducer = (state, { type, payload, options = [], optionsTransformer, compareValues }) => { switch (type) { case 'updateOptions': return { @@ -42,14 +42,11 @@ const reducer = (state, { type, payload, options = [], optionsTransformer }) => options: optionsTransformer ? optionsTransformer([ ...state.options, - ...options.filter(({ value }) => !state.options.find((option) => payload.compareValues(option.value, value))), + ...options.filter(({ value }) => !state.options.find((option) => compareValues(option.value, value))), ]) - : [...state.options, ...options.filter(({ value }) => !state.options.find((option) => payload.compareValues(option.value, value)))], + : [...state.options, ...options.filter(({ value }) => !state.options.find((option) => compareValues(option.value, value)))], ...(optionsTransformer && { - originalOptions: [ - ...state.options, - ...options.filter(({ value }) => !state.options.find((option) => payload.compareValues(option.value, value))), - ], + originalOptions: [...state.options, ...options.filter(({ value }) => !state.options.find((option) => compareValues(option.value, value)))], }), }; default: diff --git a/packages/common/src/use-select/use-select.js b/packages/common/src/use-select/use-select.js index 25e9a0e8d..308066d76 100644 --- a/packages/common/src/use-select/use-select.js +++ b/packages/common/src/use-select/use-select.js @@ -71,7 +71,7 @@ const useSelect = ({ }) => { const [propsOptions, setPropsCache] = useState(initialOptions); const [state, originalDispatch] = useReducer(reducer, { optionsTransformer, propsOptions: initialOptions }, init); - const dispatch = (action) => originalDispatch({ ...action, optionsTransformer }); + const dispatch = (action) => originalDispatch({ ...action, optionsTransformer, compareValues }); useEffect(() => { if (!isEqual(initialOptions, propsOptions)) { @@ -132,14 +132,14 @@ const useSelect = ({ const onInputChange = (inputValue) => { if (inputValue && loadOptions && state.promises[inputValue] === undefined && isSearchable) { - dispatch({ type: 'setPromises', payload: { [inputValue]: true, compareValues } }); + dispatch({ type: 'setPromises', payload: { [inputValue]: true } }); loadOptions(inputValue) .then((options) => { if (isMounted.current) { dispatch({ type: 'setPromises', - payload: { [inputValue]: false, compareValues }, + payload: { [inputValue]: false }, options, }); }