It’s a document editing application. A document title might occur in the browser’s titlebar, in the header of the main editor, in a “mention” (a link to the document) - in another document title, or in the text of a document, and in multiple places in the user’s sidebar - like in both their “Favorites” section and in the the contents of their team.
When the user edits the document title, we need to update all those UI bits to render the new title. I have a hard time imagining some imperative code that iterates over all the possible views that may render a title to mutate them. Without binding/data subscription I can’t imagine Notion working at all.
Can you show the code of the "Favorites section"? Because to me it does not sound like it is as simple to update as "Just put a reference in the template". Because what is in the users favorites is probably defined in some other data structure.
Which is what I witness in real life: In theory it sounds cool to just use data in the template and everything gets updated automatically. But in reality it is a mess with a million edge cases. Worse then just calling a list of update functions when the title changes.
Here's pseudocode of the favorite section. The "SpaceView" is a database record that represents a specific user's "view" of a shared workspace. It has a few UUID[] list columns, one of which is the "bookmarked pages" list of Block UUIDs. Methods like `.getBookedmarkedPagesStore()` get a reference "RecordStore" object to a specific column inside the record. Reading the data from a RecordStore in a component implicitly subscribes the component to changes to that column. To render lists in general, we use a <List> component. It manages drag-and-drop behavior and efficient updates, react keys, etc.
Here's the pseudocode for the main editor view. The document itself is a "Page" block database record. We render editable text with the <Text> component. We listen to contentEditable document changes, and reconcile the mutations with the rendered <Text> components to understand where the user typed and how to update our database records in response to that activity.
All updates to database records happen inside a call to `transactionActions.createAndCommit`. Under the hood, this:
1. Builds a list of commands to send to our server, to persist the user's edit to the database. Once the edits are applied on the server, we notify collaborators those records have changed, so the collaborators can pull new data and re-render their own views.
2. Optimistically updates the local, in-memory version of the database records to reflect the change commands.
3. Schedule rendering views and recomputing derivations of the views/derivations that read from the changed records.
Our React components "just" render the state of our database rows, but because we use a generic auto-tracking state system and publish change events, our views respond in near-real-time to both local and remote data changes. A new hire engineer at Notion can create a new collaborative feature on their first day with end-to-end reactivity "just" by a) rendering part of the record in a React component, and b) updating that data in the record with transactionActions.createAndCommit.
It’s a document editing application. A document title might occur in the browser’s titlebar, in the header of the main editor, in a “mention” (a link to the document) - in another document title, or in the text of a document, and in multiple places in the user’s sidebar - like in both their “Favorites” section and in the the contents of their team.
When the user edits the document title, we need to update all those UI bits to render the new title. I have a hard time imagining some imperative code that iterates over all the possible views that may render a title to mutate them. Without binding/data subscription I can’t imagine Notion working at all.