Connect callbacks to multiple elements within a react component

In order to connect a callback to a component, you have to pass that component an id prop from the dash level. Unfortunately this means that it’s not possible to pass id’s to more than one element within a custom react dash component.

I was hoping to be able to do something like this for the react component:

export const MyCustomComponent = (props) => {
  return (
    <div id={props.id}>
      <button id={props.firstButtonId}>First Button</button>
      <button id={props.secondButtonId}>Second Button</button>
    </div>
  );
};

And then be able to register callbacks to any of the elements where an id was passed:

app = dash.Dash(__name__)
app.layout = html.Div(
    [
        MyCustomComponent(
            id="outer-id",
            firstButtonId="first-button",
            secondButtonId="second-button"
        ),
        html.Div(id="button-clicked")
    ]
)

@app.callback(
    Output('button-clicked', 'children'),
    Input('first', 'n_clicks')
)
def click_first_button(n_clicks):
    return n_clicks

However this will yield the error:

ID not found in layout

The only workaround I can think of would be to pass these elements into the component via the “children” prop but this is not ideal. Another possible way to resolve this would be to allow custom props to accept components but this also is not possible as of now.

I’m curious if anyone has run into a similar issue or if there are any plans to support more complex react integration like this.

I have previously used two design approaches,

  1. Pass the components (in your case, buttons) as children from Dash (as you have already pointed out)
  2. Wire up the events (in your case, button clicks) of the child components (i.e. the buttons) to set properties of your Dash component (i.e MyCustomComponent)

As I read your example, the structure of the children (a few buttons) is fixed. In this case, I would typically use option (2). If the structure of the children is dynamic, option (1) might be a better choice.