How can I correctly obtain the updated x_range after dragging in Jupyter?

Just a note: in the notebook you really want to have new Bokeh objects created for every (re-)evaluation of the cell with show. Each new invocations results in a new session, and sessions are not designed to share objects. Typically all the “app” code is encapsulated entirely in a function like my_app, not just the add_root part. This is how things are demonstrated in the example I linked.

Alternatively, a small class can be defined for the app, which may be preferable for code organization. There was an example of that discussed here: