Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sqllab): remove set state on component update lifecycle #21771

Merged
merged 4 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 63 additions & 42 deletions superset-frontend/src/SqlLab/components/SouthPane/SouthPane.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,60 +25,25 @@ import SouthPaneContainer from 'src/SqlLab/components/SouthPane/state';
import ResultSet from 'src/SqlLab/components/ResultSet';
import '@testing-library/jest-dom/extend-expect';
import { STATUS_OPTIONS } from 'src/SqlLab/constants';
import { initialState } from 'src/SqlLab/fixtures';
import { initialState, table, defaultQueryEditor } from 'src/SqlLab/fixtures';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';

const NOOP = () => {};

const mockedProps = {
editorQueries: [
{
cached: false,
changedOn: Date.now(),
db: 'main',
dbId: 1,
id: 'LCly_kkIN',
startDttm: Date.now(),
},
{
cached: false,
changedOn: 1559238500401,
db: 'main',
dbId: 1,
id: 'lXJa7F9_r',
startDttm: 1559238500401,
},
{
cached: false,
changedOn: 1559238506925,
db: 'main',
dbId: 1,
id: '2g2_iRFMl',
startDttm: 1559238506925,
},
{
cached: false,
changedOn: 1559238516395,
db: 'main',
dbId: 1,
id: 'erWdqEWPm',
startDttm: 1559238516395,
},
],
queryEditorId: defaultQueryEditor.id,
latestQueryId: 'LCly_kkIN',
dataPreviewQueries: [],
actions: {},
activeSouthPaneTab: '',
height: 1,
displayLimit: 1,
databases: {},
offline: false,
defaultQueryLimit: 100,
};

const mockedEmptyProps = {
editorQueries: [],
queryEditorId: 'random_id',
latestQueryId: '',
dataPreviewQueries: [],
actions: {
queryEditorSetAndSaveSql: NOOP,
cloneQueryToNewTab: NOOP,
Expand All @@ -90,15 +55,66 @@ const mockedEmptyProps = {
activeSouthPaneTab: '',
height: 100,
databases: '',
offline: false,
displayLimit: 100,
user: UserWithPermissionsAndRoles,
defaultQueryLimit: 100,
};

const middlewares = [thunk];
const mockStore = configureStore(middlewares);
const store = mockStore(initialState);
const store = mockStore({
...initialState,
sqlLab: {
...initialState,
offline: false,
tables: [
{
...table,
dataPreviewQueryId: '2g2_iRFMl',
queryEditorId: defaultQueryEditor.id,
},
],
databases: {},
queries: {
LCly_kkIN: {
cached: false,
changedOn: Date.now(),
db: 'main',
dbId: 1,
id: 'LCly_kkIN',
startDttm: Date.now(),
sqlEditorId: defaultQueryEditor.id,
},
lXJa7F9_r: {
cached: false,
changedOn: 1559238500401,
db: 'main',
dbId: 1,
id: 'lXJa7F9_r',
startDttm: 1559238500401,
sqlEditorId: defaultQueryEditor.id,
},
'2g2_iRFMl': {
cached: false,
changedOn: 1559238506925,
db: 'main',
dbId: 1,
id: '2g2_iRFMl',
startDttm: 1559238506925,
sqlEditorId: defaultQueryEditor.id,
},
erWdqEWPm: {
cached: false,
changedOn: 1559238516395,
db: 'main',
dbId: 1,
id: 'erWdqEWPm',
startDttm: 1559238516395,
sqlEditorId: defaultQueryEditor.id,
},
},
},
});
const setup = (overrides = {}) => (
<SouthPaneContainer store={store} {...mockedProps} {...overrides} />
);
Expand All @@ -117,9 +133,14 @@ describe('SouthPane - Enzyme', () => {
it('should pass latest query down to ResultSet component', () => {
wrapper = getWrapper().dive();
expect(wrapper.find(ResultSet)).toExist();
expect(wrapper.find(ResultSet).props().query.id).toEqual(
// for editorQueries
expect(wrapper.find(ResultSet).first().props().query.id).toEqual(
mockedProps.latestQueryId,
);
// for dataPreviewQueries
expect(wrapper.find(ResultSet).last().props().query.id).toEqual(
'2g2_iRFMl',
);
});
});

Expand Down
3 changes: 2 additions & 1 deletion superset-frontend/src/SqlLab/components/SouthPane/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ const TAB_HEIGHT = 140;
editorQueries are queries executed by users passed from SqlEditor component
dataPrebiewQueries are all queries executed for preview of table data (from SqlEditorLeft)
*/
interface SouthPanePropTypes {
export interface SouthPanePropTypes {
queryEditorId: string;
editorQueries: any[];
latestQueryId?: string;
dataPreviewQueries: any[];
Expand Down
34 changes: 28 additions & 6 deletions superset-frontend/src/SqlLab/components/SouthPane/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,36 @@
import { connect } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import * as Actions from 'src/SqlLab/actions/sqlLab';
import SouthPane from '.';
import { SqlLabRootState } from 'src/SqlLab/types';
import SouthPane, { SouthPanePropTypes } from '.';

function mapStateToProps({ sqlLab }: Record<string, any>) {
function mapStateToProps(
{ sqlLab }: SqlLabRootState,
{ queryEditorId }: SouthPanePropTypes,
) {
const { databases, activeSouthPaneTab, offline, user, queries, tables } =
sqlLab;
const dataPreviewQueries = tables
.filter(
({ dataPreviewQueryId, queryEditorId: qeId }) =>
dataPreviewQueryId &&
queryEditorId === qeId &&
queries[dataPreviewQueryId],
)
.map(({ name, dataPreviewQueryId }) => ({
...queries[dataPreviewQueryId],
tableName: name,
}));
const editorQueries = Object.values(queries).filter(
({ sqlEditorId }) => sqlEditorId === queryEditorId,
);
return {
activeSouthPaneTab: sqlLab.activeSouthPaneTab,
databases: sqlLab.databases,
offline: sqlLab.offline,
user: sqlLab.user,
editorQueries,
dataPreviewQueries,
activeSouthPaneTab,
databases,
offline,
user,
};
}

Expand Down
6 changes: 0 additions & 6 deletions superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ const StyledSidebar = styled.div`
const propTypes = {
actions: PropTypes.object.isRequired,
tables: PropTypes.array.isRequired,
editorQueries: PropTypes.array.isRequired,
dataPreviewQueries: PropTypes.array.isRequired,
queryEditor: PropTypes.object.isRequired,
defaultQueryLimit: PropTypes.number.isRequired,
maxRow: PropTypes.number.isRequired,
Expand All @@ -150,8 +148,6 @@ const propTypes = {
const SqlEditor = ({
actions,
tables,
editorQueries,
dataPreviewQueries,
queryEditor,
defaultQueryLimit,
maxRow,
Expand Down Expand Up @@ -619,9 +615,7 @@ const SqlEditor = ({
{renderEditorBottomBar(hotkeys)}
</div>
<ConnectedSouthPane
editorQueries={editorQueries}
latestQueryId={latestQuery?.id}
dataPreviewQueries={dataPreviewQueries}
actions={actions}
height={southPaneHeight}
displayLimit={displayLimit}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { EditableTabs } from 'src/components/Tabs';
import TabbedSqlEditors from 'src/SqlLab/components/TabbedSqlEditors';
import SqlEditor from 'src/SqlLab/components/SqlEditor';
import { table, initialState } from 'src/SqlLab/fixtures';
import { initialState } from 'src/SqlLab/fixtures';
import { newQueryTabName } from 'src/SqlLab/utils/newQueryTabName';
import QueryProvider from 'src/views/QueryProvider';

Expand All @@ -43,12 +43,6 @@ describe('TabbedSqlEditors', () => {
const mockStore = configureStore(middlewares);
const store = mockStore(initialState);

const tabHistory = ['dfsadfs', 'newEditorId'];

const tables = [
{ ...table, dataPreviewQueryId: 'B1-VQU1zW', queryEditorId: 'newEditorId' },
];

const queryEditors = [
{
autorun: false,
Expand All @@ -61,14 +55,6 @@ describe('TabbedSqlEditors', () => {
name: 'Untitled Query',
},
];
const queries = {
'B1-VQU1zW': {
id: 'B1-VQU1zW',
sqlEditorId: 'newEditorId',
tableName: 'ab_user',
state: 'success',
},
};
const mockedProps = {
actions: {},
databases: {},
Expand Down Expand Up @@ -146,20 +132,6 @@ describe('TabbedSqlEditors', () => {
);
});
});
describe('UNSAFE_componentWillReceiveProps', () => {
beforeEach(() => {
wrapper = getWrapper();
wrapper.setProps({ queryEditors, queries, tabHistory, tables });
});
it('should update queriesArray and dataPreviewQueries', () => {
expect(wrapper.state().queriesArray.slice(-1)[0]).toBe(
queries['B1-VQU1zW'],
);
expect(wrapper.state().dataPreviewQueries.slice(-1)[0]).toEqual(
queries['B1-VQU1zW'],
);
});
});
it('should removeQueryEditor', () => {
wrapper = getWrapper();
sinon.stub(wrapper.instance().props.actions, 'removeQueryEditor');
Expand Down
36 changes: 0 additions & 36 deletions superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { bindActionCreators } from 'redux';
import URI from 'urijs';
import { styled, t } from '@superset-ui/core';
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
import { areArraysShallowEqual } from 'src/reduxUtils';
import { Tooltip } from 'src/components/Tooltip';
import { detectOS } from 'src/utils/common';
import * as Actions from 'src/SqlLab/actions/sqlLab';
Expand Down Expand Up @@ -72,8 +71,6 @@ class TabbedSqlEditors extends React.PureComponent {
const sqlLabUrl = '/superset/sqllab';
this.state = {
sqlLabUrl,
queriesArray: [],
dataPreviewQueries: [],
};
this.removeQueryEditor = this.removeQueryEditor.bind(this);
this.duplicateQueryEditor = this.duplicateQueryEditor.bind(this);
Expand Down Expand Up @@ -186,37 +183,6 @@ class TabbedSqlEditors extends React.PureComponent {
}
}

UNSAFE_componentWillReceiveProps(nextProps) {
const nextActiveQeId =
nextProps.tabHistory[nextProps.tabHistory.length - 1];
const queriesArray = Object.values(nextProps.queries).filter(
query => query.sqlEditorId === nextActiveQeId,
);
if (!areArraysShallowEqual(queriesArray, this.state.queriesArray)) {
this.setState({ queriesArray });
}

const dataPreviewQueries = [];
nextProps.tables.forEach(table => {
const queryId = table.dataPreviewQueryId;
if (
queryId &&
nextProps.queries[queryId] &&
table.queryEditorId === nextActiveQeId
) {
dataPreviewQueries.push({
...nextProps.queries[queryId],
tableName: table.name,
});
}
});
if (
!areArraysShallowEqual(dataPreviewQueries, this.state.dataPreviewQueries)
) {
this.setState({ dataPreviewQueries });
}
}

popNewTab() {
// Clean the url in browser history
window.history.replaceState({}, document.title, this.state.sqlLabUrl);
Expand Down Expand Up @@ -298,8 +264,6 @@ class TabbedSqlEditors extends React.PureComponent {
<SqlEditor
tables={this.props.tables.filter(xt => xt.queryEditorId === qe.id)}
queryEditor={qe}
editorQueries={this.state.queriesArray}
dataPreviewQueries={this.state.dataPreviewQueries}
actions={this.props.actions}
defaultQueryLimit={this.props.defaultQueryLimit}
maxRow={this.props.maxRow}
Expand Down