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

[BUG] Bug with Dash DataTable with Pagination #2347

Open
akashsivanandan99 opened this issue Dec 1, 2022 · 4 comments
Open

[BUG] Bug with Dash DataTable with Pagination #2347

akashsivanandan99 opened this issue Dec 1, 2022 · 4 comments

Comments

@akashsivanandan99
Copy link

I've run into a bug with Dash datatables, where tables with pagination that have tooltips keep generating errors if you hover over them. The DataTable becomes non responsive after the errors are thrown, and doesn't work until you refresh the app.

Made a simple dash app to reproduce the error. To trigger the issue navigate the table until you find the highlighted cell and hover over the table. The dash app code is:

from datetime import date

import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd

from dash.dependencies import Input, Output
import pandas as pd

import dash

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv"
)[["country", "pop", "continent", "lifeExp"]]

print("Columns: ", df.columns)

app = dash.Dash(__name__)

app.layout = html.Div([
    dash_table.DataTable(
        id='datatable-row-ids',
        columns=[
            {'name': i, 'id': i, 'deletable': True} for i in df.columns
            # omit the id column
            if i != 'id'
        ],
        data=df.to_dict('records'),
        editable=True,
        filter_action="native",
        sort_action="native",
        sort_mode='multi',
        row_selectable='multi',
        row_deletable=True,
        selected_rows=[],
        page_action='native',
        page_current= 0,
        page_size= 10,
        style_data_conditional = [
            {
                        'if': {'row_index': 'odd'},
                        'backgroundColor': '#F4F5F7'
                    },
            {
                'if': {
                            'filter_query': '{country} = "India"',
                            'column_id': 'continent',
                        },
                        'backgroundColor': '#FEFAF3',
                        'color': '#E29F08',
            }
        ],
        tooltip_conditional = [
            {
                'if': {
                            'filter_query': '{country} = "India"',
                            'column_id': 'continent',
                        },
                        'type': 'markdown',
                        'value': 'Country: India',
            }
        ]
    ),
    html.Div(id='datatable-row-ids-container')
])


if __name__ == "__main__":
    app.run_server(debug=True)

My environment is as follows:

dash                      1.21.0
dash-bootstrap-components 0.13.0
dash-core-components      1.17.1
dash-html-components      1.1.4
dash-table                4.12.0

The error thrown in debug is:

This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)

resolve@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:175548

3446/hs/</<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:178094

3446/hs/<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:178228

3446/e/<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:174615

3446/Af</u</<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:280023

3446/Af</u<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:280035

3446/wc<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:207524

1294/i/<@http://127.0.0.1:8050/_dash-component-suites/dash_table/bundle.v4_12_0m1668077809.js:1:23324

t@http://127.0.0.1:8050/_dash-component-suites/dash_table/bundle.v4_12_0m1668077809.js:1:21684

3446/Af</c<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:279873

3446/Af<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:280363

5117/o/<@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:632

value@http://127.0.0.1:8050/_dash-component-suites/dash_table/async-table.js:2:305876

finishClassComponent@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:17295:33

updateClassComponent@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:17245:46

beginWork@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:18755:18

beginWork$1@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:23314:16

performUnitOfWork@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:22292:14

workLoopSync@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:22265:24

performSyncWorkOnRoot@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:21891:11

flushSyncCallbackQueueImpl/<@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:11224:26

unstable_runWithPriority@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react@16.v1_21_0m1668077809.14.0.js:2685:14

runWithPriority$1@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:11174:12

flushSyncCallbackQueueImpl@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:11219:26

flushSyncCallbackQueue@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:11207:5

batchedEventUpdates$1@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:22012:9

batchedEventUpdates@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:792:14

dispatchEventForLegacyPluginEventSystem@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:3691:26

attemptToDispatchEvent@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:4390:46

dispatchEvent@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:4312:43

unstable_runWithPriority@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react@16.v1_21_0m1668077809.14.0.js:2685:14

dispatchUserBlockingUpdate@http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v1_21_0m1668077809.14.0.js:4295:20

Screenshots

Screenshot 2022-12-01 at 8 14 33 PM

@ned2
Copy link
Contributor

ned2 commented Dec 3, 2022

You're running a rather old version of Dash (1.21.0 was released in July 2021). So I took this for a spin on Dash 2.7.0 and can confirm that this problem still exists. Here's a more minimal example that displays the issue:

from datetime import date
from dash import dcc, html, dash_table, Input, Output, Dash
import pandas as pd

df = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv"
)
app = Dash(__name__)
app.layout = dash_table.DataTable(
    columns=[{"name": col, "id": col} for col in df.columns],
    data=df.to_dict("records"),
    page_size=10,
    tooltip_conditional=[
        {
            "if": {
                "filter_query": '{country} = "Albania"',
                "column_id": "continent",
            },
            "value": "Country: Albania",
        }
    ],
)

if __name__ == "__main__":
    app.run_server(debug=True)

The issue appears to involve the combination of the conditional tooltip while on a page beyond the first: when the app loads and before changing pages, hovering over the cell in the second row in the "continent" column triggers the tooltip, as expected (as the country value is "Albania"), however after moving to the second page, hovering over any cell in the content column will trigger a pile of JavaScript errors and make the app unresponsive.

@aneeshdua
Copy link

@alexcjohnson Can i pick this up?

@alexcjohnson
Copy link
Collaborator

@aneeshdua go for it! Let me know if you have any trouble finding the right areas of the source code to poke around.

@aneeshdua
Copy link

@alexcjohnson @ned2 I am also able to reproduce the bug.

The two React console errors that occur are as follows:

The above error occurred in the <u> component:
    in u (created by c)
    in c (created by s)
    in s (created by c)
    in Suspense (created by c)
    in c (created by CheckedComponent)
    in CheckedComponent (created by BaseTreeContainer)
    in ComponentErrorBoundary (created by BaseTreeContainer)
    in BaseTreeContainer (created by DashWrapper)
    in DashWrapper (created by UnconnectedContainer)
    in div (created by UnconnectedGlobalErrorContainer)
    in div (created by GlobalErrorOverlay)
    in div (created by GlobalErrorOverlay)
    in GlobalErrorOverlay (created by DebugMenu)
    in div (created by DebugMenu)
    in DebugMenu (created by UnconnectedGlobalErrorContainer)
    in div (created by UnconnectedGlobalErrorContainer)
    in UnconnectedGlobalErrorContainer (created by Connect(UnconnectedGlobalErrorContainer))
    in Connect(UnconnectedGlobalErrorContainer) (created by UnconnectedContainer)
    in UnconnectedContainer (created by Connect(UnconnectedContainer))
    in Connect(UnconnectedContainer) (created by UnconnectedAppContainer)
    in UnconnectedAppContainer (created by Connect(UnconnectedAppContainer))
    in Connect(UnconnectedAppContainer) (created by AppProvider)
    in Provider (created by AppProvider)
    in AppProvider

React will try to recreate this component tree from scratch using the error boundary you provided, ComponentErrorBoundary.
error.js:16 TypeError: Cannot read properties of undefined (reading 'country')
    at Object.resolve (expression.ts:12:20)
    at relational.ts:9:35
    at Object.evaluate (relational.ts:18:33)
    at i.evaluate (index.ts:47:32)
    at index.ts:5:31
    at index.ts:51:9
    at findLast.js:35:9
    at _dispatchable.js:44:15
    at Object.t (_curry2.js:28:14)
    at tooltip.ts:17:11

I believe the 1st error is of the dash-renderer component and my hunch is the problem lies in the tooltip_conditional code of the dash-table component. Based on the 2nd error, I was able to make out a few points:

  • The function getSelectedTooltip() [defined here] can return undefined based on the conditional nature of the tooltips.
  • The undefined response is not handled in the QuerySyntaxTree() [called here]

Please let me know if I am in the right direction. Meanwhile, I will try to dig deeper into the Syntax-tree part of the dash-table code. If possible please share the overall role of the syntax-tree code.

P.S. - I am still novice to open source. Please correct me if I make a mistake. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants