Upgrading - Upgrading to 2.0
Liveblocks 2.0 is our second major release, and focuses on removing any rough edges and smoothening the developer experience. It makes Liveblocks simpler to set up for new users as well as for existing users. Our long term goal is to empower you to write and evolve your apps in the best way possible, and at enterprise scale.
Rationale
Liveblocks has always embraced the benefits of static typing with TypeScript.
Roughly two years ago, we published 0.17, which
introduced the pattern of calling
createRoomContext()
and returning a “bundle” of type-safe hooks that you could
then use in your application. This pattern worked nicely because all the hooks
were bound to your custom type definitions for Presence
, Storage
, etc. in
one single place, and every Liveblocks API would deeply know about it. No need
for manual type annotations anywhere else in your codebase.
Downsides to this approach
There were, however, a couple of downsides to this approach that have always kept itching:
- Importing hooks from a local config file was a little bit awkward. It wasn’t an all too familiar pattern for most users.
- Re-exporting the list of hooks took maintenance. If we added a new hook, you’d have to also re-export it manually.
- Due to how TypeScript works, the type params you’d provide to
createRoomContext()
had a fixed ordering to them. If you wanted to specify onlyPresence
andRoomEvent
, you’d have to “skip” some type params, by doingcreateRoomContext<Presence, {}, {}, RoomEvent>()
or similar.
Introducing Liveblocks 2.0
With 2.0, this all becomes a lot simpler. We’ve done a lot of internal refactoring to make this possible. We’ll dive in soon, but here is a sneak peek:
We’ll first go over all the breaking changes, then we’ll show you how to simplify your codebase.
How to upgrade
First of all, let’s upgrade all Liveblocks dependencies to their latest versions. The easiest way to do that is to run the following command:
There are also some breaking changes in this update. Most users will not run into any of these, but there is a chance that some of these will affect your situation. Making the necessary code adjustments should however be easy. In many cases, we provide a codemod that makes the actual change for you, so you don’t have to do so manually.
Breaking change 1: renamed package
We’ve renamed our package @liveblocks/react-comments
to
@liveblocks/react-ui
, because our library of pre-built UI components now
contains more than just Comments-related components. Please adjust your imports.
Run the following codemod or manually make the changes:
This will change your imports like this:
And also:
Breaking change 2: renamed exports in our Node package
To avoid confusion with the newly introduced custom
RoomInfo
type, we’ve renamed the RoomInfo
type
in our @liveblocks/node
package.
Run the following codemod or manually make the changes:
This will change:
Breaking change 3: client methods from our Node package no longer take type params
In @liveblocks/node
, none of the client methods, like
liveblocks.getThread()
, take type params any longer.
Make the following changes:
You should use global type augmentation instead. Please see “Simplifying your Liveblocks application” below for a lot more detail on this transition.
Breaking change 4: changed default export to named export in Yjs package
To make discoverability and refactorings easier, and to avoid confusion with the
newly introduced LiveblocksProvider
in our React package, we’re no longer
using default exports, but named exports only.
Run the following codemod or manually make the changes:
This will change your import (and its usage) like this:
Breaking change 5: minor LiveList constructor change
The LiveList()
constructor’s argument is no longer optional, because it causes
unneeded but confusing type inference issues.
Run the following codemod or manually make the changes:
This will add an array to empty LiveList
constructors:
Breaking change 6: new webhook event types
The webhook event NotificationEvent
’s type can represent multiple kinds of
notifications: "thread"
, "textMention"
, and custom ones (e.g.
"$myNotification"
).
If you were using properties only available on the "thread"
kind (e.g.
threadId
), you will need to first check for the kind of notification before
accessing them.
Breaking change 7: removed deprecated APIs
All of the following APIs have been removed in 2.0, as they were deprecated multiple versions ago.
Affecting @liveblocks/client
:
Client.enter()
has been replaced byClient.enterRoom()
Client.leave()
has been replaced byClient.enterRoom()
, which returns aleave
function- Client option
fetchPolyfill
,WebSocketPolyfill
, are replaced bypolyfills: { fetch, WebSocket }
- Legacy option
shouldInitiallyConnect
is now renamed toautoConnect
- Legacy connection status APIs, e.g.
room.getConnectionState()
and.subscribe("connection")
. You can use.getStatus()
or.subscribe("status")
instead. user.isReadOnly
field is replaced by!user.canWrite
(note the negation here)- The
Others<P, U>
type. Please change toreadonly User<P, U>[]
.
Affecting @liveblocks/react
:
- The
useMap
,useList
, anduseObject
hooks. These have been deprecated since the release of 0.18 (more than two years ago). Please see the 0.18 upgrade guide for tips on how to rewrite these hooks touseStorage
. - The second argument
options
tocreateRoomContext(client, options)
has been removed. These options have been moved to the client.
Affecting @liveblocks/node
:
- Remove legacy
authorize
method from@liveblocks/node
. Please refer to the 1.2 upgrade guide to learn how to upgrade your auth endpoint.
Affecting @liveblocks/redux
and @liveblocks/zustand
:
- Legacy aliased exports in Zustand/Redux packages are removed
Simplifying your Liveblocks application (optional)
If you have dealt with the breaking changes above, or concluded they they don’t apply to your situation, we can go a step further and really simplify your Liveblocks setup.
Step 1: Use the new global Liveblocks custom types
Go to your liveblocks.config.ts
, find your createRoomContext()
call. Now
decide which codemod to run.
Option 1: You are using Suspense hooks.
(const { suspense: { useRoom, ... } }
)
Option 2: You are using classic hooks. (const { useRoom, ... }
)
Running either of these will make the following changes.
Secondly, it will change all imports in your code base to import the hooks directly instead:
Step 2: Set up a LiveblocksProvider
At this point, there should not be any new TypeScript issues. However, running
the code will not yet work. This is because previously the hooks were bound to
the client
instance by passing it to the createRoomContext()
factory, which
we now removed. When using the global types, we’ll have to provide the
Liveblocks client otherwise.
The way to do it is to use a pretty standard React provider. Make the following change:
If you were exporting the client
instance before and have components that
directly accessed it before, you can now obtain a reference to the client
instance that the LiveblocksProvider
creates for you using the useClient
hook:
Step 3: Optional cleanup of type params
If you also exported your Presence
, Storage
, etc types from
liveblocks.config.ts
before, you no longer have to. The main reason to export
these before was to use them in helper functions that used some of the
Liveblocks types, like User
, or Room
.
For example:
This is no longer needed. You can simply remove them. TypeScript will still know
about your custom age
property on user.info
.
Improvements
Furthermore, the following miscellaneous quality-of-life improvements have been made that are non-breaking changes.
ClientSideSuspense
no longer needs a function
Previously, the ClientSideSuspense
helper needed a function as its children
prop, but it no longer has to.
This will change:
Improved InboxNotification
props types
When passing custom components to the kinds
prop of InboxNotification
,
you could use types like InboxNotificationThreadProps
for the props. But this
wasn’t always true for all notification kinds, so now you can use types named
InboxNotificationThreadKindProps
for your components, while
InboxNotificationThreadProps
describes the props of our own
InboxNotification.Thread
.
New custom type RoomInfo
By using the resolveRoomsInfo
callback from createClient
or the new
LiveblocksProvider
, you can attach arbitrary room data to a room, which
you can retrieve with the useRoomInfo
hook.
Both of these APIs will now respect the type you provide via:
New custom type ActivitiesData
By providing a custom ActivitiesData
type, you can improve how your custom
notifications and their activities’ data are typed.
That’s it!
Questions? Please ask!
If you have any trouble with these new patterns, run into a bug with one of the codemods, or otherwise need help, please let us know by email or by joining our Discord community! We’re here to help!