Connect Callbacks to elements in nested react component

Hello,

I hope this is the correct sub board. I am trying to write my own component using the boiler plate repository to visualise some graph data structure.

This component will fetch stuff from another server and visualize it. (If possible) I would like to support dash callbacks when someone clicks on elements in this component, but I am unable to connect the setProps and callbacks correctly.

I understand that this question might be way too basic, a pointer to some indepth tutorials would be really helpful.

Ideally I want to keep the python dash part as minimal as possible:

from my_app import MyComponent
app.layout = html.Div([
    MyComponent("myID"),
    html.Div(id='output')
])

@app.callback(Output('output', 'children'), Input({'type': 'node', 'id': ALL}, 'node')) 
def clicked_on(node):
  return f"You clicked on ${node}"

If I’m correct, I have to use the setProps function to send something back to dash. But the function never gets called. Below I pasted an example of how my main Component looks and the Parts that I want to click on.

Hope someone can help me, thank you very much!


class Node extends Component {
    render() {
        const {id, notifyClick} = this.props;
        return <div onClick={() => notifyClick({"type": "node", id: id})}>{id}</div>
    }

}

export default class MyComponent extends Component {

    state = {
        externalData: null
    };

    render() {
        const {id, setProps} = this.props;
        if (this.state.externalData === null) {
            return <div>Loading..</div>
        }
        return (<div>{this.state.externalData.map((id) => <Node key={id} id={id} notifyClick={setProps}/>)}</div>)
    }


    loadMyAsyncData() {
        const {id} = this.props;
        return fetch(`someserver`).then(r => r.json())
    }

    componentDidMount() {
        this._asyncRequest = this.loadMyAsyncData().then(
            externalData => {
                this._asyncRequest = null;
                this.setState({externalData});
            }
        );
    }

    componentWillUnmount() {
        if (this._asyncRequest) {
            this._asyncRequest.cancel();
        }
    }
}
MyComponent.propTypes = {
    /**
     * The ID used to identify this component in Dash callbacks.
     */
    id: PropTypes.string,

    /**
     * Dash-assigned callback that should be called to report property changes
     * to Dash, to make them available for callbacks.
     */
    setProps: PropTypes.func
};

As I understand, you must attach the Dash callback to your component, i.e. the callback signature should be something like

@app.callback(Output('output', 'children'), Input('myID', 'node')) 
def clicked_on(node):

Then, in the React layer you would use the onClick event to update the node property of your component whenever a node is clicked using syntax like,

this.props.setProps({node: THE_NODE_THAT_WAS_CLICKED_ON})

from within the event handler. For inspiration, you could take a look at the EasyButton.

3 Likes

Hey Emil,

thanks a lot for the reply, that helped a lot!

1 Like