# Synchronizing VR State — Live

Synchronize Five SDK view state between host and audience participants in Live.

Canonical: https://developer.realsee.ai/docs/live/get-started/sync-five-state
Source: https://developer.realsee.ai/docs/live/get-started/sync-five-state.md
Language: en

> **info**

Backed by the full-duplex communication of long-lived WebSocket connections, Live lets users across multiple clients join the same session and stay in sync. Within its messaging system, **keyframe data** is the payload that carries this synchronization. This chapter explains how to keep VR views in sync.
**Before you start building synchronization, you need at least two co-viewing roles: a host and a viewer.**
We also assume that you already know how to read and set Five SDK state.

## Framework-free Example


**JavaScript**


```jsx
five.on("stateChange", (state, userAction) => {
  // Listen for changes to the local Five state
  if (userAction) {
    // Send only Five state changes triggered by user actions
    // Send the local keyframe data (Five State)
    live.sendKeyframe("FiveState", state);
  }
});

// Receive remote keyframe data (Five State)
live.keyframes.on("FiveState", (newState, prevState) => {
  // Use the latest `newState` to update the local UI state
  five.setState(newState, false, false); // Set userAction to false to avoid an infinite sync loop.
});
```


**TypeScript**


```tsx
five.on("stateChange", (state, userAction) => {
  // Listen for changes to the local Five state
  if (userAction) {
    // Send only Five state changes triggered by user actions
    // Send the local keyframe data (Five State)
    live.sendKeyframe("FiveState", state);
  }
});

// Receive remote keyframe data (Five State)
live.keyframes.on("FiveState", (newState, prevState) => {
  // Use the latest `newState` to update the local UI state
  five.setState(newState, false, false); // Set userAction to false to avoid an infinite sync loop.
});
```



> **tip**

Operate the VR view as the `host`, then inspect the ws traffic in the Network tab of the `host` console.

As the VR view changes on the host's screen, the ws Messages continuously emit `KEYFRAME_SYNC` commands. Click a command to view the detailed payload that was transmitted.

![Chrome DevTools showing outbound KEYFRAME_SYNC WebSocket messages with FiveState data](https://developer.realsee.ai/assets/docs/live/live-five-state-sync.png)


> **tip**

At the same time, inspect the `viewer` console and find the ws traffic in the Network tab.

As the host operates the VR view, the ws Messages receive `KEYFRAME_SYNC` commands. Click a command to view the detailed payload that was received.

![Chrome DevTools showing received KEYFRAME_SYNC WebSocket messages with FiveState data](https://developer.realsee.ai/assets/docs/live/live-five-state-receive.png)


> **tip**

Outgoing ws messages are shown as green arrows pointing up, and incoming ws messages are shown as red arrows pointing down.

## React Example


**JavaScript**


```jsx
import LiveReact from "LiveReact";
import { useFiveState } from "@realsee/five/react";

const { useKeyframe } = LiveReact;

function Test() {
  const [fiveState, setFiveState] = useFiveState();
  const [fiveStateKeyframe, setFiveStateKeyframe] = useKeyframe("FiveState");

  // Listen for Five state changes and send keyframe data
  useFiveEventCallback("stateChange", (state, userAction) => {
    // Send only the state changes triggered by the user
    if (userAction) {
      setFiveStateKeyframe(state);
    }
  });

  // Receive keyframe data
  /*
   * In `const [fiveStateKeyframe, setFiveStateKeyframe] = useKeyframe('FiveState')`,
   * the useKeyframe() hook already keeps the real-time keyframe data updated, so
   * `fiveStateKeyframe` is always the latest Five state keyframe.
   * Therefore, receiving keyframe data only requires diffing the value of the
   * first parameter returned by the useKeyframe() hook and then updating the local UI.
   * Here you only need to watch for changes to `fiveStateKeyframe` and then update the Five state.
   * */

  React.useEffect(() => {
    // Reaching this point means `fiveStateKeyframe` has changed.
    setFiveState(fiveStateKeyframe, false, false); // Set userAction to false for the synced state change to avoid an infinite sync loop.
  }, [fiveStateKeyframe]);

  return null;
}
```


**TypeScript**


```tsx
import LiveReact from "LiveReact";
import { useFiveState } from "@realsee/five/react";

const { useKeyframe } = LiveReact;

function Test() {
  const [fiveState, setFiveState] = useFiveState();
  const [fiveStateKeyframe, setFiveStateKeyframe] = useKeyframe("FiveState");

  // Listen for Five state changes and send keyframe data
  useFiveEventCallback("stateChange", (state, userAction) => {
    // Send only the state changes triggered by the user
    if (userAction) {
      setFiveStateKeyframe(state);
    }
  });

  // Receive keyframe data
  /*
   * In `const [fiveStateKeyframe, setFiveStateKeyframe] = useKeyframe('FiveState')`,
   * the useKeyframe() hook already keeps the real-time keyframe data updated, so
   * `fiveStateKeyframe` is always the latest Five state keyframe.
   * Therefore, receiving keyframe data only requires diffing the value of the
   * first parameter returned by the useKeyframe() hook and then updating the local UI.
   * Here you only need to watch for changes to `fiveStateKeyframe` and then update the Five state.
   * */

  React.useEffect(() => {
    // Reaching this point means `fiveStateKeyframe` has changed.
    setFiveState(fiveStateKeyframe, false, false); // Set userAction to false for the synced state change to avoid an infinite sync loop.
  }, [fiveStateKeyframe]);

  return null;
}
```



> **tip**

Operate the VR view as the `host`, then inspect the ws traffic in the Network tab of the `host` console.

As the VR view changes on the host's screen, the ws Messages continuously emit `KEYFRAME_SYNC` commands. Click a command to view the detailed payload that was transmitted.

![Chrome DevTools showing outbound KEYFRAME_SYNC WebSocket messages with FiveState data](https://developer.realsee.ai/assets/docs/live/live-five-state-sync.png)


> **tip**

At the same time, inspect the `viewer` console and find the ws traffic in the Network tab.

As the host operates the VR view, the ws Messages receive `KEYFRAME_SYNC` commands. Click a command to view the detailed payload that was received.

![Chrome DevTools showing received KEYFRAME_SYNC WebSocket messages with FiveState data](https://developer.realsee.ai/assets/docs/live/live-five-state-receive.png)


> **tip**

Outgoing ws messages are shown as green arrows pointing up, and incoming ws messages are shown as red arrows pointing down.
