diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 58440989bd3..fdee143bf06 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -83,6 +83,7 @@ module.exports = { 'plugin:react-hooks/recommended', 'plugin:react-prefer-function-component/recommended', 'plugin:storybook/recommended', + 'plugin:react-you-might-not-need-an-effect/legacy-recommended', ], parser: '@babel/eslint-parser', parserOptions: { diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index f40a8105f03..492847eabb0 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -232,6 +232,7 @@ "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-prefer-function-component": "^3.3.0", + "eslint-plugin-react-you-might-not-need-an-effect": "^0.5.1", "eslint-plugin-storybook": "^0.8.0", "eslint-plugin-testing-library": "^6.4.0", "eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors", @@ -25929,6 +25930,36 @@ "dev": true, "license": "MIT" }, + "node_modules/eslint-plugin-react-you-might-not-need-an-effect": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-you-might-not-need-an-effect/-/eslint-plugin-react-you-might-not-need-an-effect-0.5.1.tgz", + "integrity": "sha512-Gi2kfHLkXUT3j+IAwgb8TEhY10iMwsdwSsgbIxk98zPpuPW7M52ey9fU1oPZrWUlyekr5eXwUCjeTHekS6Isrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-utils": "^3.0.0", + "globals": "^16.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": ">=8.40.0" + } + }, + "node_modules/eslint-plugin-react-you-might-not-need-an-effect/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -26044,6 +26075,25 @@ "node": ">=4.0" } }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, "node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 7915b82d19e..e51858cb4e1 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -305,6 +305,7 @@ "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-prefer-function-component": "^3.3.0", + "eslint-plugin-react-you-might-not-need-an-effect": "^0.5.1", "eslint-plugin-storybook": "^0.8.0", "eslint-plugin-testing-library": "^6.4.0", "eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors", diff --git a/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx index adfa1f7bcbe..bf8c99263d4 100644 --- a/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx +++ b/superset-frontend/packages/superset-ui-core/src/components/Select/Select.tsx @@ -127,13 +127,9 @@ const Select = forwardRef( const shouldShowSearch = allowNewOptions ? true : showSearch; const [selectValue, setSelectValue] = useState(value); const [inputValue, setInputValue] = useState(''); - const [isLoading, setIsLoading] = useState(loading); const [isDropdownVisible, setIsDropdownVisible] = useState(false); const [isSearching, setIsSearching] = useState(false); const [visibleOptions, setVisibleOptions] = useState([]); - const [maxTagCount, setMaxTagCount] = useState( - propsMaxTagCount ?? MAX_TAG_COUNT, - ); const [onChangeCount, setOnChangeCount] = useState(0); const previousChangeCount = usePrevious(onChangeCount, 0); const fireOnChange = useCallback( @@ -141,11 +137,11 @@ const Select = forwardRef( [onChangeCount], ); - useEffect(() => { - if (oneLine) { - setMaxTagCount(isDropdownVisible ? 0 : 1); - } - }, [isDropdownVisible, oneLine]); + const maxTagCount = oneLine + ? isDropdownVisible + ? 0 + : 1 + : (propsMaxTagCount ?? MAX_TAG_COUNT); const mappedMode = isSingleMode ? undefined : 'multiple'; @@ -510,6 +506,8 @@ const Select = forwardRef( ], ); + const isLoading = loading ?? false; + const popupRender = ( originNode: ReactElement & { ref?: RefObject }, ) => @@ -536,12 +534,6 @@ const Select = forwardRef( setVisibleOptions(initialOptions); }, [initialOptions]); - useEffect(() => { - if (loading !== undefined && loading !== isLoading) { - setIsLoading(loading); - } - }, [isLoading, loading]); - useEffect(() => { setSelectValue(value); }, [value]);