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/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 92c93981f..308066d76 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,8 +69,15 @@ const useSelect = ({ simpleValue, compareValues, }) => { - const [state, originalDispatch] = useReducer(reducer, { optionsTransformer, propsOptions }, init); - const dispatch = (action) => originalDispatch({ ...action, optionsTransformer }); + const [propsOptions, setPropsCache] = useState(initialOptions); + const [state, originalDispatch] = useReducer(reducer, { optionsTransformer, propsOptions: initialOptions }, init); + const dispatch = (action) => originalDispatch({ ...action, optionsTransformer, compareValues }); + + useEffect(() => { + if (!isEqual(initialOptions, propsOptions)) { + setPropsCache(initialOptions); + } + }, [initialOptions]); const isMounted = useIsMounted(); @@ -114,7 +121,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); } @@ -125,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, }); }