diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 88cdb65a5..203e2144e 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -149,6 +149,7 @@ "@testing-library/dom": "^7.29.4", "@testing-library/jest-dom": "^5.11.6", "@testing-library/react": "^11.2.0", + "@testing-library/react-hooks": "^5.0.3", "@testing-library/user-event": "^12.7.0", "@types/classnames": "^2.2.10", "@types/dom-to-image": "^2.6.0", @@ -302,6 +303,8 @@ "integrity": "sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ==", "dev": true, "dependencies": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents", + "chokidar": "^3.4.0", "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", @@ -7107,6 +7110,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -7710,6 +7714,7 @@ "jest-resolve": "^26.6.2", "jest-util": "^26.6.2", "jest-worker": "^26.6.2", + "node-notifier": "^8.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", @@ -7898,6 +7903,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -8329,6 +8335,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -10115,7 +10122,8 @@ "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -10797,6 +10805,9 @@ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz", "integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==", "dev": true, + "dependencies": { + "clipboard": "^2.0.0" + }, "optionalDependencies": { "clipboard": "^2.0.0" } @@ -16402,6 +16413,49 @@ "node": ">=10" } }, + "node_modules/@testing-library/react-hooks": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-5.0.3.tgz", + "integrity": "sha512-UrnnRc5II7LMH14xsYNm/WRch/67cBafmrSQcyFh0v+UUmSf1uzfB7zn5jQXSettGwOSxJwdQUN7PgkT0w22Lg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/react": ">=16.9.0", + "@types/react-dom": ">=16.9.0", + "@types/react-test-renderer": ">=16.9.0", + "filter-console": "^0.1.1", + "react-error-boundary": "^3.1.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0", + "react-test-renderer": ">=16.9.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, + "node_modules/@testing-library/react-hooks/node_modules/react-error-boundary": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.0.tgz", + "integrity": "sha512-lmPrdi5SLRJR+AeJkqdkGlW/CRkAUvZnETahK58J4xb5wpbfDngasEGu+w0T1iXEhVrYBJZeW+c4V1hILCnMWQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/@testing-library/user-event": { "version": "12.7.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.7.0.tgz", @@ -17049,6 +17103,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-test-renderer": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", + "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", @@ -20129,6 +20192,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -21947,6 +22011,7 @@ "anymatch": "^2.0.0", "async-each": "^1.0.0", "braces": "^2.3.0", + "fsevents": "^1.2.2", "glob-parent": "^3.1.0", "inherits": "^2.0.1", "is-binary-path": "^1.0.0", @@ -22708,6 +22773,7 @@ "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", "dev": true, "dependencies": { + "colors": "^1.1.2", "object-assign": "^4.1.0", "string-width": "^4.2.0" }, @@ -26338,7 +26404,8 @@ "esprima": "^3.1.3", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -28921,6 +28988,15 @@ "node": ">=0.10.0" } }, + "node_modules/filter-console": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/filter-console/-/filter-console-0.1.1.tgz", + "integrity": "sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", @@ -32440,6 +32516,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -33279,6 +33356,7 @@ "@jest/types": "^24.9.0", "anymatch": "^2.0.0", "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", "graceful-fs": "^4.1.15", "invariant": "^2.2.4", "jest-serializer": "^24.9.0", @@ -34052,6 +34130,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -35698,6 +35777,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -36020,6 +36100,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -36390,6 +36471,7 @@ "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", "jest-serializer": "^26.6.2", @@ -37550,7 +37632,8 @@ "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -38071,8 +38154,11 @@ "dependencies": { "errno": "^0.1.1", "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", "make-dir": "^2.1.0", "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0", "tslib": "^1.10.0" }, "bin": { @@ -43781,6 +43867,9 @@ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", "dev": true, + "dependencies": { + "clipboard": "^2.0.0" + }, "optionalDependencies": { "clipboard": "^2.0.0" } @@ -45399,6 +45488,7 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", + "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -46741,6 +46831,9 @@ "version": "1.22.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz", "integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==", + "dependencies": { + "clipboard": "^2.0.0" + }, "optionalDependencies": { "clipboard": "^2.0.0" } @@ -49678,7 +49771,8 @@ "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.8.1" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "bin": { "escodegen": "bin/escodegen.js", @@ -53103,8 +53197,10 @@ "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "dev": true, "dependencies": { + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" }, "optionalDependencies": { "chokidar": "^3.4.1", @@ -54017,6 +54113,7 @@ "anymatch": "^2.0.0", "async-each": "^1.0.1", "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", "inherits": "^2.0.3", "is-binary-path": "^1.0.0", @@ -70509,6 +70606,31 @@ "@testing-library/dom": "^7.27.1" } }, + "@testing-library/react-hooks": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-5.0.3.tgz", + "integrity": "sha512-UrnnRc5II7LMH14xsYNm/WRch/67cBafmrSQcyFh0v+UUmSf1uzfB7zn5jQXSettGwOSxJwdQUN7PgkT0w22Lg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@types/react": ">=16.9.0", + "@types/react-dom": ">=16.9.0", + "@types/react-test-renderer": ">=16.9.0", + "filter-console": "^0.1.1", + "react-error-boundary": "^3.1.0" + }, + "dependencies": { + "react-error-boundary": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.0.tgz", + "integrity": "sha512-lmPrdi5SLRJR+AeJkqdkGlW/CRkAUvZnETahK58J4xb5wpbfDngasEGu+w0T1iXEhVrYBJZeW+c4V1hILCnMWQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + } + } + }, "@testing-library/user-event": { "version": "12.7.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.7.0.tgz", @@ -71152,6 +71274,15 @@ "@types/react": "*" } }, + "@types/react-test-renderer": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-17.0.1.tgz", + "integrity": "sha512-3Fi2O6Zzq/f3QR9dRnlnHso9bMl7weKCviFmfF6B4LS1Uat6Hkm15k0ZAQuDz+UBq6B3+g+NM6IT2nr5QgPzCw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-transition-group": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", @@ -81364,6 +81495,12 @@ "to-regex-range": "^2.1.0" } }, + "filter-console": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/filter-console/-/filter-console-0.1.1.tgz", + "integrity": "sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg==", + "dev": true + }, "finalhandler": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 5dcff95b0..984a9e17a 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -201,6 +201,7 @@ "@testing-library/dom": "^7.29.4", "@testing-library/jest-dom": "^5.11.6", "@testing-library/react": "^11.2.0", + "@testing-library/react-hooks": "^5.0.3", "@testing-library/user-event": "^12.7.0", "@types/classnames": "^2.2.10", "@types/dom-to-image": "^2.6.0", diff --git a/superset-frontend/src/common/hooks/useComponentDidMount/index.ts b/superset-frontend/src/common/hooks/useComponentDidMount/index.ts new file mode 100644 index 000000000..f6c2eeafa --- /dev/null +++ b/superset-frontend/src/common/hooks/useComponentDidMount/index.ts @@ -0,0 +1,20 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './useComponentDidMount'; diff --git a/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.test.ts b/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.test.ts new file mode 100644 index 000000000..6d7d6cd71 --- /dev/null +++ b/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.test.ts @@ -0,0 +1,28 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { renderHook } from '@testing-library/react-hooks'; +import { useComponentDidMount } from './useComponentDidMount'; + +test('the effect should only be executed on the first render', () => { + const effect = jest.fn(); + const hook = renderHook(() => useComponentDidMount(effect)); + expect(effect).toBeCalledTimes(1); + hook.rerender(); + expect(effect).toBeCalledTimes(1); +}); diff --git a/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.ts b/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.ts new file mode 100644 index 000000000..a906f4d87 --- /dev/null +++ b/superset-frontend/src/common/hooks/useComponentDidMount/useComponentDidMount.ts @@ -0,0 +1,24 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { EffectCallback, useEffect } from 'react'; + +export const useComponentDidMount = (effect: EffectCallback) => { + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(effect, []); +}; diff --git a/superset-frontend/src/components/FlashProvider/FlashProvider.test.tsx b/superset-frontend/src/components/FlashProvider/FlashProvider.test.tsx new file mode 100644 index 000000000..c91c0a0a4 --- /dev/null +++ b/superset-frontend/src/components/FlashProvider/FlashProvider.test.tsx @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { Provider } from 'react-redux'; +import { store } from 'src/views/store'; +import FlashProvider, { FlashMessage } from './index'; + +test('Rerendering correctly with default props', () => { + const messages: FlashMessage[] = []; + render( + + +
My Component
+
+
, + ); + expect(screen.getByTestId('my-component')).toBeInTheDocument(); +}); + +test('messages should only be inserted in the State when the component is mounted', () => { + const messages: FlashMessage[] = [ + ['info', 'teste message 01'], + ['info', 'teste message 02'], + ]; + expect(store.getState().messageToasts).toEqual([]); + const { rerender } = render( + + +
My Component
+
+
, + ); + const fistRender = store.getState().messageToasts; + expect(fistRender).toHaveLength(2); + expect(fistRender[1].text).toBe(messages[0][1]); + expect(fistRender[0].text).toBe(messages[1][1]); + + rerender( + + +
My Component
+
+
, + ); + + const secondRender = store.getState().messageToasts; + expect(secondRender).toEqual(fistRender); +}); diff --git a/superset-frontend/src/components/FlashProvider.tsx b/superset-frontend/src/components/FlashProvider/index.tsx similarity index 64% rename from superset-frontend/src/components/FlashProvider.tsx rename to superset-frontend/src/components/FlashProvider/index.tsx index 5ecbc3279..21c1fff54 100644 --- a/superset-frontend/src/components/FlashProvider.tsx +++ b/superset-frontend/src/components/FlashProvider/index.tsx @@ -16,17 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; -import withToasts from 'src/messageToasts/enhancers/withToasts'; +import { useToasts } from 'src/messageToasts/enhancers/withToasts'; +import { useComponentDidMount } from 'src/common/hooks/useComponentDidMount'; -type Message = Array; +type FlashMessageType = 'info' | 'alert' | 'danger' | 'warning' | 'success'; +export type FlashMessage = [FlashMessageType, string]; -interface CommonObject { - flash_messages: Array; -} interface Props { - children: Node; - common: CommonObject; + children: JSX.Element; + messages: FlashMessage[]; } const flashObj = { @@ -37,21 +35,17 @@ const flashObj = { success: 'addSuccessToast', }; -class FlashProvider extends React.PureComponent { - componentDidMount() { - const flashMessages = this.props.common.flash_messages; - flashMessages.forEach(message => { +export default function FlashProvider({ children, messages }: Props) { + const toasts = useToasts(); + useComponentDidMount(() => { + messages.forEach(message => { const [type, text] = message; const flash = flashObj[type]; - if (this.props[flash]) { - this.props[flash](text); + const toast = toasts[flash]; + if (toast) { + toast(text); } }); - } - - render() { - return this.props.children; - } + }); + return children; } - -export default withToasts(FlashProvider); diff --git a/superset-frontend/src/explore/components/ExploreViewContainer.jsx b/superset-frontend/src/explore/components/ExploreViewContainer.jsx index bb508121e..71d163aa7 100644 --- a/superset-frontend/src/explore/components/ExploreViewContainer.jsx +++ b/superset-frontend/src/explore/components/ExploreViewContainer.jsx @@ -35,6 +35,7 @@ import { setInLocalStorage, } from 'src/utils/localStorageHelpers'; import { URL_PARAMS } from 'src/constants'; +import cx from 'classnames'; import ExploreChartPanel from './ExploreChartPanel'; import ConnectedControlPanelsContainer from './ControlPanelsContainer'; import SaveModal from './SaveModal'; @@ -528,9 +529,10 @@ function ExploreViewContainer(props) { />
{renderChartContainer()}
diff --git a/superset-frontend/src/views/App.tsx b/superset-frontend/src/views/App.tsx index 0e8dc243f..babc03f3d 100644 --- a/superset-frontend/src/views/App.tsx +++ b/superset-frontend/src/views/App.tsx @@ -18,8 +18,6 @@ */ import React, { Suspense } from 'react'; import { hot } from 'react-hot-loader/root'; -import thunk from 'redux-thunk'; -import { createStore, applyMiddleware, compose, combineReducers } from 'redux'; import { Provider as ReduxProvider } from 'react-redux'; import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; @@ -34,9 +32,8 @@ import { theme } from 'src/preamble'; import ToastPresenter from 'src/messageToasts/containers/ToastPresenter'; import setupPlugins from 'src/setup/setupPlugins'; import setupApp from 'src/setup/setupApp'; -import messageToastReducer from 'src/messageToasts/reducers'; -import { initEnhancer } from 'src/reduxUtils'; import { routes, isFrontendRoute } from 'src/views/routes'; +import { store } from './store'; setupApp(); setupPlugins(); @@ -48,19 +45,10 @@ const menu = { ...bootstrap.common.menu_data }; const common = { ...bootstrap.common }; initFeatureFlags(bootstrap.common.feature_flags); -const store = createStore( - combineReducers({ - messageToasts: messageToastReducer, - common: () => common, - }), - {}, - compose(applyMiddleware(thunk), initEnhancer(false)), -); - const App = () => ( - + common, + }), + {}, + compose(applyMiddleware(thunk), initEnhancer(false)), +);