React Core and Components

If you're building with React, our React SDK makes it simple to add real-time audio and video to your app. We provide state management and media rendering utility components, allowing you to implement custom UI components and designs. The same SDK also includes pre-built components for constructing video calls or audio rooms with little code.

While this bundled structure functions well, one downside of including pre-built components is a bloated dependency tree. Occasionally, our version of a dependency would conflict with the version a developer was already using, forcing them to upgrade or downgrade their own. Furthermore, elements like icons, popovers, and buttons are included in applications which don't use them, increasing an app's bundle size, which can be detrimental to a user's experience.

After observing the vastly different ways LiveKit is being used, it's clear many developers are building apps that require custom logic and/or user interfaces. A more modular approach to our React SDK design lets developers download only the dependencies they need, while also granting us flexibility to offer other higher-level abstractions down the road.

Introducing react-core​ and react-components

Instead of a single package containing both core building blocks and pre-built components, we now publish two flavors of our React SDK:

When to use which?

@livekit/react-core​ takes care of tricky state synchronization and playback issues while holding no opinion over UI/UX.  It exports two hooks, useRoom and useParticipant, that subscribe to RoomEvents and ParticipantEvents, providing the current state of a room and participant, respectively.  react-core also provides two components, AudioRenderer and VideoRenderer, for actually playing track media with the correct settings for cross-browser compatibility.

Here's an example of useRoom, useParticipant, AudioRenderer, and VideoRenderer in action:

const Stage = () => {
  const { room, isConnecting, participants, audioTracks } = useRoom({
    adaptiveStream: true,
    dynacast: true,

  return (
      // the position of AudioRenderer in the DOM is not super important
      { => {
        <AudioRenderer track={t} isLocal={false} />

      { => (
        <ParticipantView participant={p} />

const ParticipantView = ({ participant }) => {
  // isSpeaking, connectionQuality will update when changed
  const { isSpeaking, connectionQuality, isLocal, cameraPublication } = useParticipant(participant);

  if (cameraPublication?.isMuted ?? true) {
    return <div>No video</div>;
  // user is not subscribed to track, for when using selective subscriptions
  if (!cameraPublication.isSubscribed) {
    return null;

  return (
    <VideoRenderer track={cameraPublication.track} isLocal={isLocal} />

If you're looking to get something working as quickly as possible, the pre-made UI components in @livekit/react-components​ are for you. You can easily extend, style, or even fork these components. Here's a quick example, using our default renderers:

import { LiveKitRoom } from '@livekit/react-components';
import '@livekit/react-components/dist/index.css';
import 'react-aspect-ratio/aspect-ratio.css';

export const RoomPage = () => { 
  const url = 'wss://your_host';
  const token = 'your_token';
  return (
    <div className="roomContainer">
      <LiveKitRoom url={url} token={token} onConnected={room => onConnected(room)}/>

async function onConnected(room) {
  await room.localParticipant.setCameraEnabled(true);
  await room.localParticipant.setMicrophoneEnabled(true);

If you're already using our legacy livekit-react ​package, you won't encounter any problems just switching to the new @livekit/react-components​ package, which provides the same components and helpers as the old package. Internally, it builds on top of the @livekit/react-core​ package.

Update your livekit-react dependency

Even if you're happy with the state of our (now legacy) livekit-react ​package, we recommend you update your dependency to @livekit/react-components​. We are no longer publishing updates to the livekit-react​ npm package. Again, the new package provides the same components and helpers, so the transition should be seamless.

Every JavaScript developer knows how bloated node_modules can get. Splitting our React SDK into @livekit/react-core and @livekit/react-components lets you use exactly what you need, and nothing more.

We're looking forward to the flexibility this new organization will give you (and us) in the future. Stay tuned for some neat improvements and extensions to these packages we'll add in the coming months.

You can find the release notes for our 1.0 version in the LiveKit React repo on GitHub.

As always, if you have any questions or comments, feel free to drop in to our LiveKit Community Slack.  We'd love to hear from you, and we're always happy to help with any issues you might encounter!