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)),
+);