diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 7a13d6b7187..740f2735abb 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -135,7 +135,7 @@ "urijs": "^1.19.8", "use-event-callback": "^0.1.0", "use-immer": "^0.11.0", - "use-query-params": "^1.1.9", + "use-query-params": "^2.2.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "yargs": "^17.7.2" }, @@ -53153,13 +53153,10 @@ } }, "node_modules/serialize-query-params": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-1.3.6.tgz", - "integrity": "sha512-VlH7sfWNyPVZClPkRacopn6sn5uQMXBsjPVz1+pBHX895VpcYVznfJtZ49e6jymcrz+l/vowkepCZn/7xEAEdw==", - "license": "ISC", - "peerDependencies": { - "query-string": ">=5.1.1" - } + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-2.0.4.tgz", + "integrity": "sha512-y9WzzDj3BsGgKLCh0ugiinufS//YqOfao/yVJjkXA4VLuyNCfHOLU/cbulGPxs3aeCqhvROw7qPL04JSZnCo0w==", + "license": "ISC" }, "node_modules/serve-index": { "version": "1.9.1", @@ -57955,17 +57952,26 @@ } }, "node_modules/use-query-params": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/use-query-params/-/use-query-params-1.2.3.tgz", - "integrity": "sha512-cdG0tgbzK+FzsV6DAt2CN8Saa3WpRnze7uC4Rdh7l15epSFq7egmcB/zuREvPNwO5Yk80nUpDZpiyHsoq50d8w==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/use-query-params/-/use-query-params-2.2.2.tgz", + "integrity": "sha512-OwGab8u8/x2xZp9uSyBsx0kXlkR9IR436zbygsYVGikPYY3OJosvve6IJVGwIJPcfyb/YHwvPrUNu65/JR++Kw==", "license": "ISC", "dependencies": { - "serialize-query-params": "^1.3.5" + "serialize-query-params": "^2.0.3" }, "peerDependencies": { - "query-string": ">=5.1.1", + "@reach/router": "^1.2.1", "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "react-dom": ">=16.8.0", + "react-router-dom": ">=5" + }, + "peerDependenciesMeta": { + "@reach/router": { + "optional": true + }, + "react-router-dom": { + "optional": true + } } }, "node_modules/use-sync-external-store": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 8eea2c1ebf7..7e77bcc8230 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -217,7 +217,7 @@ "urijs": "^1.19.8", "use-event-callback": "^0.1.0", "use-immer": "^0.11.0", - "use-query-params": "^1.1.9", + "use-query-params": "^2.2.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "yargs": "^17.7.2" }, diff --git a/superset-frontend/spec/helpers/ProviderWrapper.tsx b/superset-frontend/spec/helpers/ProviderWrapper.tsx index d8d63cf3de6..33d5b6bad3f 100644 --- a/superset-frontend/spec/helpers/ProviderWrapper.tsx +++ b/superset-frontend/spec/helpers/ProviderWrapper.tsx @@ -18,8 +18,10 @@ */ import { ThemeProvider } from '@apache-superset/core/ui'; -import { BrowserRouter as Router, Route } from 'react-router-dom'; +import { parse, stringify } from 'query-string'; +import { BrowserRouter as Router } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; export function ProviderWrapper(props: any) { const { children, theme } = props; @@ -28,8 +30,12 @@ export function ProviderWrapper(props: any) { ) => + stringify(object, { encode: false }), + }} > {children} diff --git a/superset-frontend/spec/helpers/testing-library.tsx b/superset-frontend/spec/helpers/testing-library.tsx index 1a841a32483..151c5d54e75 100644 --- a/superset-frontend/spec/helpers/testing-library.tsx +++ b/superset-frontend/spec/helpers/testing-library.tsx @@ -43,6 +43,7 @@ import { configureStore, Store } from '@reduxjs/toolkit'; import { api } from 'src/hooks/apiResources/queryApi'; import userEvent from '@testing-library/user-event'; import { ExtensionsProvider } from 'src/extensions/ExtensionsContext'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; type Options = Omit & { useRedux?: boolean; @@ -109,7 +110,11 @@ export function createWrapper(options?: Options) { } if (useQueryParams) { - result = {result}; + result = ( + + {result} + + ); } if (useRouter) { diff --git a/superset-frontend/src/components/ListView/ListView.test.tsx b/superset-frontend/src/components/ListView/ListView.test.tsx index 6434b11839f..f278e607ac6 100644 --- a/superset-frontend/src/components/ListView/ListView.test.tsx +++ b/superset-frontend/src/components/ListView/ListView.test.tsx @@ -19,6 +19,8 @@ import { render, screen, within, waitFor } from 'spec/helpers/testing-library'; import userEvent from '@testing-library/user-event'; import { QueryParamProvider } from 'use-query-params'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; +import { MemoryRouter } from 'react-router-dom'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import { ReactNode } from 'react'; @@ -51,16 +53,6 @@ type MockedListViewProps = Omit< const middlewares = [thunk]; const mockStore = configureStore(middlewares); -function makeMockLocation(query?: string) { - const queryStr = query ? encodeURIComponent(query) : ''; - return { - protocol: 'http:', - host: 'localhost', - pathname: '/', - search: queryStr.length ? `?${queryStr}` : '', - } as Location; -} - const fetchSelectsMock = jest.fn(() => Promise.resolve({ data: [], totalCount: 0 }), ); @@ -214,9 +206,11 @@ test('redirects to first page when page index is invalid', async () => { const factory = (overrides?: Partial) => { const props = { ...mockedPropsComprehensive, ...overrides }; return render( - - - , + + + + + , { store: mockStore() }, ); }; diff --git a/superset-frontend/src/embedded/EmbeddedContextProviders.tsx b/superset-frontend/src/embedded/EmbeddedContextProviders.tsx index c7b2b48ae8e..a2a43b16d6e 100644 --- a/superset-frontend/src/embedded/EmbeddedContextProviders.tsx +++ b/superset-frontend/src/embedded/EmbeddedContextProviders.tsx @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -import { Route } from 'react-router-dom'; import { getExtensionsRegistry } from '@superset-ui/core'; import { Provider as ReduxProvider } from 'react-redux'; import { QueryParamProvider } from 'use-query-params'; @@ -28,6 +27,8 @@ import { SupersetThemeProvider } from 'src/theme/ThemeProvider'; import { ThemeController } from 'src/theme/ThemeController'; import type { ThemeStorage } from '@apache-superset/core/ui'; import { store } from 'src/views/store'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; +import { parse, stringify } from 'query-string'; /** * In-memory implementation of ThemeStorage interface for embedded contexts. @@ -69,8 +70,12 @@ export const EmbeddedContextProviders: React.FC = ({ children }) => { ) => + stringify(object, { encode: false }), + }} > {RootContextProviderExtension ? ( diff --git a/superset-frontend/src/features/allEntities/AllEntitiesTable.test.tsx b/superset-frontend/src/features/allEntities/AllEntitiesTable.test.tsx index 149ca183b03..98bd548b4bd 100644 --- a/superset-frontend/src/features/allEntities/AllEntitiesTable.test.tsx +++ b/superset-frontend/src/features/allEntities/AllEntitiesTable.test.tsx @@ -18,7 +18,6 @@ */ import { render, screen } from 'spec/helpers/testing-library'; -import * as useQueryParamsModule from 'use-query-params'; import AllEntitiesTable from './AllEntitiesTable'; // eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks @@ -82,12 +81,6 @@ describe('AllEntitiesTable', () => { ], }; - beforeEach(() => { - jest - .spyOn(useQueryParamsModule, 'useQueryParam') - .mockReturnValue([42, jest.fn()]); - }); - afterEach(() => { jest.restoreAllMocks(); }); diff --git a/superset-frontend/src/features/home/RightMenu.test.tsx b/superset-frontend/src/features/home/RightMenu.test.tsx index e861a00342a..78002025b44 100644 --- a/superset-frontend/src/features/home/RightMenu.test.tsx +++ b/superset-frontend/src/features/home/RightMenu.test.tsx @@ -212,6 +212,7 @@ test('renders', async () => { resetUseSelectorMock(); const { container } = render(, { useRedux: true, + useRouter: true, useQueryParams: true, useTheme: true, }); @@ -225,6 +226,7 @@ test('If user has permission to upload files AND connect DBs we query existing D resetUseSelectorMock(); const { container } = render(, { useRedux: true, + useRouter: true, useQueryParams: true, useTheme: true, }); diff --git a/superset-frontend/src/pages/AlertReportList/AlertReportList.test.jsx b/superset-frontend/src/pages/AlertReportList/AlertReportList.test.jsx index 80ef800b88e..85dd7d9f4af 100644 --- a/superset-frontend/src/pages/AlertReportList/AlertReportList.test.jsx +++ b/superset-frontend/src/pages/AlertReportList/AlertReportList.test.jsx @@ -28,6 +28,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import AlertList from 'src/pages/AlertReportList'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -86,7 +87,7 @@ fetchMock.delete(alertsEndpoint, {}); const renderAlertList = (props = {}) => render( - + , diff --git a/superset-frontend/src/pages/AnnotationLayerList/AnnotationLayerList.test.jsx b/superset-frontend/src/pages/AnnotationLayerList/AnnotationLayerList.test.jsx index 4ebcf526107..d3fc63221be 100644 --- a/superset-frontend/src/pages/AnnotationLayerList/AnnotationLayerList.test.jsx +++ b/superset-frontend/src/pages/AnnotationLayerList/AnnotationLayerList.test.jsx @@ -29,6 +29,7 @@ import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import AnnotationLayersList from 'src/pages/AnnotationLayerList'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -76,7 +77,7 @@ fetchMock.get(layersRelatedEndpoint, { const renderAnnotationLayersList = (props = {}) => render( - + , diff --git a/superset-frontend/src/pages/ChartList/ChartList.permissions.test.tsx b/superset-frontend/src/pages/ChartList/ChartList.permissions.test.tsx index 5406f7b4caf..b5dd95211c9 100644 --- a/superset-frontend/src/pages/ChartList/ChartList.permissions.test.tsx +++ b/superset-frontend/src/pages/ChartList/ChartList.permissions.test.tsx @@ -25,6 +25,7 @@ import { QueryParamProvider } from 'use-query-params'; import { isFeatureEnabled } from '@superset-ui/core'; import ChartList from 'src/pages/ChartList'; import { API_ENDPOINTS, mockCharts, setupMocks } from './ChartList.testHelpers'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; // Increase default timeout for all tests jest.setTimeout(30000); @@ -116,7 +117,7 @@ const renderChartList = ( return render( - + diff --git a/superset-frontend/src/pages/ChartList/ChartList.test.tsx b/superset-frontend/src/pages/ChartList/ChartList.test.tsx index cd0b95befe4..a515fcc9059 100644 --- a/superset-frontend/src/pages/ChartList/ChartList.test.tsx +++ b/superset-frontend/src/pages/ChartList/ChartList.test.tsx @@ -31,12 +31,6 @@ import { setupMocks, } from './ChartList.testHelpers'; -const mockPush = jest.fn(); -jest.mock('react-router-dom', () => ({ - ...jest.requireActual('react-router-dom'), - useHistory: () => ({ push: mockPush }), -})); - jest.mock('@superset-ui/core', () => ({ ...jest.requireActual('@superset-ui/core'), isFeatureEnabled: jest.fn(), @@ -76,7 +70,6 @@ describe('ChartList', () => { beforeEach(() => { fetchMock.removeRoutes(); setupMocks(); - mockPush.mockClear(); }); afterEach(() => { @@ -107,9 +100,12 @@ describe('ChartList', () => { fireEvent.click(newChartButton); // Verify it triggers navigation to chart creation - await waitFor(() => { - expect(mockPush).toHaveBeenCalledWith('/chart/add'); - }); + await waitFor( + () => { + expect(window.location.pathname).toEqual('/chart/add'); + }, + { timeout: 5000 }, + ); }); test('verify Import button existence and functionality', async () => { diff --git a/superset-frontend/src/pages/ChartList/ChartList.testHelpers.tsx b/superset-frontend/src/pages/ChartList/ChartList.testHelpers.tsx index d6518a0a4df..53934e66dc7 100644 --- a/superset-frontend/src/pages/ChartList/ChartList.testHelpers.tsx +++ b/superset-frontend/src/pages/ChartList/ChartList.testHelpers.tsx @@ -20,11 +20,12 @@ import fetchMock from 'fetch-mock'; import { render } from 'spec/helpers/testing-library'; import { Provider } from 'react-redux'; -import { MemoryRouter } from 'react-router-dom'; +import { BrowserRouter } from 'react-router-dom'; import { configureStore } from '@reduxjs/toolkit'; import { QueryParamProvider } from 'use-query-params'; import ChartList from 'src/pages/ChartList'; import handleResourceExport from 'src/utils/export'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; export const mockHandleResourceExport = handleResourceExport as jest.MockedFunction; @@ -268,11 +269,11 @@ export const renderChartList = (user: any, props = {}, storeState = {}) => { return render( - - + + - + , ); }; diff --git a/superset-frontend/src/pages/CssTemplateList/CssTemplateList.test.jsx b/superset-frontend/src/pages/CssTemplateList/CssTemplateList.test.jsx index d8f17c541a4..c24a094f20a 100644 --- a/superset-frontend/src/pages/CssTemplateList/CssTemplateList.test.jsx +++ b/superset-frontend/src/pages/CssTemplateList/CssTemplateList.test.jsx @@ -29,6 +29,7 @@ import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import CssTemplatesList from 'src/pages/CssTemplateList'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -75,7 +76,7 @@ fetchMock.get(templatesRelatedEndpoint, { const renderCssTemplatesList = (props = {}) => render( - + , diff --git a/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx b/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx index 18879e4e676..c9daf3caa8f 100644 --- a/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx +++ b/superset-frontend/src/pages/DashboardList/DashboardList.test.jsx @@ -28,6 +28,7 @@ import { import { QueryParamProvider } from 'use-query-params'; import DashboardList from 'src/pages/DashboardList'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const dashboardsInfoEndpoint = 'glob:*/api/v1/dashboard/_info*'; const dashboardOwnersEndpoint = 'glob:*/api/v1/dashboard/related/owners*'; @@ -89,7 +90,7 @@ describe('DashboardList', () => { const renderDashboardList = (props = {}, userProp = mockUser) => render( - + , @@ -225,7 +226,7 @@ describe('DashboardList - anonymous view', () => { test('does not render favorite stars for anonymous user', async () => { render( - + , diff --git a/superset-frontend/src/pages/GroupsList/GroupsList.test.tsx b/superset-frontend/src/pages/GroupsList/GroupsList.test.tsx index 4acb6c21d47..328064248a2 100644 --- a/superset-frontend/src/pages/GroupsList/GroupsList.test.tsx +++ b/superset-frontend/src/pages/GroupsList/GroupsList.test.tsx @@ -31,6 +31,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import GroupsList from './index'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -66,7 +67,7 @@ fetchMock.get(rolesEndpoint, { count: 3, }); -fetchMock.get(groupsEndpoint, { result: [] }); +fetchMock.get(groupsEndpoint, { result: [] }, { name: groupsEndpoint }); jest.mock('src/dashboard/util/permissionUtils', () => ({ ...jest.requireActual('src/dashboard/util/permissionUtils'), @@ -79,7 +80,7 @@ describe('GroupsList', () => { await act(async () => { render( - + , @@ -113,7 +114,7 @@ describe('GroupsList', () => { expect(await screen.findByTestId('Add Group-modal')).toBeInTheDocument(); }); - test.only('renders actions column for admin', async () => { + test('renders actions column for admin', async () => { await renderComponent(); expect(screen.getAllByText('Actions')[0]).toBeInTheDocument(); }); @@ -129,7 +130,7 @@ describe('GroupsList', () => { expect(within(filtersSelect).getByText(/users/i)).toBeInTheDocument(); }); - test.only('renders correct columns in the table', async () => { + test('renders correct columns in the table', async () => { await renderComponent(); const table = screen.getByRole('table'); @@ -147,6 +148,7 @@ describe('GroupsList', () => { }); test('opens edit modal on edit button click', async () => { + fetchMock.removeRoute(groupsEndpoint); fetchMock.get('glob:*/security/groups/?*', { result: [ { diff --git a/superset-frontend/src/pages/RolesList/RolesList.test.tsx b/superset-frontend/src/pages/RolesList/RolesList.test.tsx index eca699352ed..fd0c814e869 100644 --- a/superset-frontend/src/pages/RolesList/RolesList.test.tsx +++ b/superset-frontend/src/pages/RolesList/RolesList.test.tsx @@ -30,6 +30,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import RolesList from './index'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -107,7 +108,7 @@ describe('RolesList', () => { const mockedProps = {}; render( - + {}} diff --git a/superset-frontend/src/pages/RowLevelSecurityList/RowLevelSecurityList.test.tsx b/superset-frontend/src/pages/RowLevelSecurityList/RowLevelSecurityList.test.tsx index f68c44d03d8..1174530fe2a 100644 --- a/superset-frontend/src/pages/RowLevelSecurityList/RowLevelSecurityList.test.tsx +++ b/superset-frontend/src/pages/RowLevelSecurityList/RowLevelSecurityList.test.tsx @@ -22,6 +22,7 @@ import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import userEvent from '@testing-library/user-event'; import RowLevelSecurityList from '.'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const ruleListEndpoint = 'glob:*/api/v1/rowlevelsecurity/?*'; const ruleInfoEndpoint = 'glob:*/api/v1/rowlevelsecurity/_info*'; @@ -109,7 +110,7 @@ describe('RuleList RTL', () => { const mockedProps = {}; render( - + , diff --git a/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.tsx b/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.tsx index dc89f50fc14..8b660fe544d 100644 --- a/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.tsx +++ b/superset-frontend/src/pages/SavedQueryList/SavedQueryList.test.tsx @@ -28,6 +28,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import SavedQueryList from '.'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; // Increase default timeout jest.setTimeout(30000); @@ -85,7 +86,7 @@ fetchMock.delete(queryEndpoint, {}, { name: queryEndpoint }); const renderList = (props = {}, storeOverrides = {}) => render( - + , diff --git a/superset-frontend/src/pages/UserInfo/UserInfo.test.tsx b/superset-frontend/src/pages/UserInfo/UserInfo.test.tsx index e12ce245b4e..f447d6d324b 100644 --- a/superset-frontend/src/pages/UserInfo/UserInfo.test.tsx +++ b/superset-frontend/src/pages/UserInfo/UserInfo.test.tsx @@ -30,6 +30,7 @@ import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import UserInfo from 'src/pages/UserInfo'; import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -64,7 +65,7 @@ describe('UserInfo', () => { act(async () => { render( - + , diff --git a/superset-frontend/src/pages/UsersList/UsersList.test.tsx b/superset-frontend/src/pages/UsersList/UsersList.test.tsx index 62ff7ff4756..9a0d0b7d75e 100644 --- a/superset-frontend/src/pages/UsersList/UsersList.test.tsx +++ b/superset-frontend/src/pages/UsersList/UsersList.test.tsx @@ -30,6 +30,7 @@ import { import { MemoryRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import UsersList from './index'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -100,7 +101,7 @@ describe('UsersList', () => { const mockedProps = {}; render( - + , diff --git a/superset-frontend/src/views/RootContextProviders.tsx b/superset-frontend/src/views/RootContextProviders.tsx index c10f04ae816..a0dece042ae 100644 --- a/superset-frontend/src/views/RootContextProviders.tsx +++ b/superset-frontend/src/views/RootContextProviders.tsx @@ -17,7 +17,6 @@ * under the License. */ -import { Route } from 'react-router-dom'; import { getExtensionsRegistry } from '@superset-ui/core'; import { Provider as ReduxProvider } from 'react-redux'; import { QueryParamProvider } from 'use-query-params'; @@ -30,6 +29,8 @@ import { ThemeController } from 'src/theme/ThemeController'; import { ExtensionsProvider } from 'src/extensions/ExtensionsContext'; import { store } from './store'; import '../preamble'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; +import { parse, stringify } from 'query-string'; const themeController = new ThemeController(); const extensionsRegistry = getExtensionsRegistry(); @@ -46,8 +47,12 @@ export const RootContextProviders: React.FC = ({ children }) => { ) => + stringify(object, { encode: false }), + }} > {RootContextProviderExtension ? ( diff --git a/superset-frontend/src/views/menu.tsx b/superset-frontend/src/views/menu.tsx index fd72529bee2..5cffb94f4fd 100644 --- a/superset-frontend/src/views/menu.tsx +++ b/superset-frontend/src/views/menu.tsx @@ -22,7 +22,7 @@ import 'src/public-path'; // eg, backend rendered views import { Provider } from 'react-redux'; import ReactDOM from 'react-dom'; -import { Route, BrowserRouter } from 'react-router-dom'; +import { BrowserRouter } from 'react-router-dom'; import { CacheProvider } from '@emotion/react'; import { QueryParamProvider } from 'use-query-params'; import createCache from '@emotion/cache'; @@ -30,6 +30,8 @@ import { ThemeProvider, theme } from '@apache-superset/core/ui'; import Menu from 'src/features/home/Menu'; import getBootstrapData from 'src/utils/getBootstrapData'; import { setupStore } from './store'; +import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; +import { parse, stringify } from 'query-string'; // Disable connecting to redux debugger so that the React app injected // Below the menu like SqlLab or Explore can connect its redux store to the debugger @@ -48,8 +50,12 @@ const app = ( ) => + stringify(object, { encode: false }), + }} >