TypeError: update_data() missing 1 required positional argument: 'n_clicks'

Hello,

New to python and Dash and am having trouble creating a reddit dashboard with multiple buttons for sorting options. I almost got it working, but for some reason I always get a argument error on the last argument from the update function and I can’t figure out why.

Here’s the error:

Here’s my code:

import json
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table
import pandas as pd
import praw
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate

reddit = praw.Reddit(client_id=client_id, client_secret=client_secret, user_agent=user_agent)


def df_reddit(post_list):
    posts = []
    for post in post_list:
        posts.append([post.title, post.score, post.upvote_ratio, post.num_comments, post.selftext, post.created, 'https://reddit.com/' + post.id, post.url])

    df = pd.DataFrame(posts, columns=['title', 'score', 'up_ratio', 'comments', 'post', 'created', 'id', 'url'])
    return df


new_posts = df_reddit(reddit.subreddit('cryptocurrency').new(limit=100))


app = dash.Dash(__name__)

app.layout = html.Div([
    html.P(html.Div(html.H3('Reddit Dashboard'))),
    html.P(html.Button('Sort: New', id='new')),
    html.P(html.Button('Sort: Hot', id='hot')),
    html.P(html.Button('Sort: Rising', id='rising')),
    html.P(html.Button('Sort: Top', id='top')),
    html.P(html.Button('Sort: Controversial', id='controversial')),
    dash_table.DataTable(
        id='table'
        , style_cell_conditional=[
            {'if': {'column_id': 'title'},
             'width': '600px'},
            {'if': {'column_id': 'score'},
             'width': '100px'},
            {'if': {'column_id': 'comments'},
             'width': '100px'},
            {'if': {'column_id': 'created'},
             'width': '100px'},
            {'if': {'column_id': 'up_ratio'},
             'width': '100px'},
            {'if': {'column_id': 'id'},
             'width': '250px'},
            {'if': {'column_id': 'post'},
             'width': '800px'}
        ]
        , style_data={
            'text-align': 'left'
        }
        , style_table={
            'height': '800px',
            'maxWidth': '10000px',
            'maxHeight': '10000px',
            'overflowY': 'auto',
        }
        , style_data_conditional=[
            {
                'if': {
                    'column_id': 'post',
                },
                # 'whiteSpace': 'normal',
                'height': 'auto',
                'maxWidth': '800px'
            }
            , {
                'if': {
                    'column_id': 'title',
                },
                'whiteSpace': 'normal',
                'height': '40px',
            }
            , {
                'if': {
                    'column_id': 'score',
                    'filter_query': '{score} gt 9'
                },
                'backgroundColor': '#3D9970',
                'color': 'white',
            }
            , {
                'if': {
                    'column_id': 'score',
                    'filter_query': '{score} lt 1'
                },
                'backgroundColor': '#B20000',
                'color': 'white',
            }
            , {
                'if': {
                    'column_id': 'up_ratio',
                    'filter_query': '{up_ratio} gt 0.50'
                },
                'backgroundColor': '#3D9970',
                'color': 'white',
            }
            , {
                'if': {
                    'column_id': 'up_ratio',
                    'filter_query': '{up_ratio} lt 0.50'
                },
                'backgroundColor': '#B20000',
                'color': 'white',
            }
            , {
                'if': {
                    'column_id': 'unique density',
                    'filter_query': '{unique density} lt 0.7'
                },
                'backgroundColor': '#3D9970',
                'color': 'white',
            }
        ]
        , columns=[{"name": i, "id": i} for i in new_posts.columns]
        , fixed_rows={'headers': True, 'data': 0}
        , data=new_posts.to_dict('records')
    )
])


@app.callback(Output('table', 'data'),
              Input('new', 'n_clicks'),
              Input('hot', 'n_clicks'),
              Input('rising', 'n_clicks'),
              Input('top', 'n_clicks'),
              Input('controversial', 'n_clicks'))
def update_data(new, hot, rising, top, controversial, n_clicks):

    ctx = dash.callback_context

    if not ctx.triggered:
        button_id = 'No clicks yet'
    else:
        button_id = ctx.triggered[0]['prop_id'].split('.')[0]

    if n_clicks is None:
        raise PreventUpdate
    else:
        if button_id == 'new':
            posts = df_reddit(reddit.subreddit('cryptocurrency').new(limit=20))
        if button_id == 'hot':
            posts = df_reddit(reddit.subreddit('cryptocurrency').hot(limit=20))
        if button_id == 'rising':
            posts = df_reddit(reddit.subreddit('cryptocurrency').rising(limit=20))
        if button_id == 'top':
            posts = df_reddit(reddit.subreddit('cryptocurrency').top(limit=20))
        elif button_id == 'controversial':
            posts = df_reddit(reddit.subreddit('cryptocurrency').controversial(limit=20))

    dff = posts.copy()


    return dff.to_dict('records')


if __name__ == '__main__':
    app.run_server(debug=True, port=8050)

Hi @testingmediation and welcome to the Community.

Your callback has five inputs:

              Input('new', 'n_clicks'),
              Input('hot', 'n_clicks'),
              Input('rising', 'n_clicks'),
              Input('top', 'n_clicks'),
              Input('controversial', 'n_clicks'))

But the function has six variables:

def update_data(new, hot, rising, top, controversial, n_clicks):

Not sure I understand you. Isn’t the n_clicks an additional input in this context? How should I rewrite the callback to include the n_click as a variable?

Thanks.

@testingmediation

I’m saying that your callback has five Inputs(), then you need one variable to each one, but you added six:

Each input has two fields, one for the id of the component and the other for the property of this component, in your callback the inputs Id are:

              Input('new', 
              Input('hot',
              Input('rising', 
              Input('top', 
              Input('controversial',

All of them has the property n_clicks selected as second field.

But the variables that will take all this n_clicks are:

new, hot, rising, top, controversial, n_clicks

That means the last variable n_clicks is not needed or you need to add an additional Input(‘id’, for this variable.