Skip to main content
Real calls run on imperfect networks and busy devices. useNetwork and useCPULoad let you surface connection quality to users and adapt the UI when conditions degrade.

Show network quality

useNetwork returns the current networkState, the reasons behind it, and the connection topology:
import { useNetwork } from '@daily-co/daily-react';

function NetworkBadge() {
  const { networkState } = useNetwork();
  // 'good' | 'warning' | 'bad' | 'unknown'
  const color = { good: 'green', warning: 'orange', bad: 'red' }[networkState] ?? 'gray';
  return <span style={{ color }}>{networkState}</span>;
}
When the state is 'warning' or 'bad', networkStateReasons tells you why ('sendPacketLoss', 'recvPacketLoss', 'roundTripTime', 'availableOutgoingBitrate'), which is useful for a tooltip or a targeted hint:
const { networkState, networkStateReasons } = useNetwork();
if (networkState === 'bad' && networkStateReasons.includes('sendPacketLoss')) {
  // Suggest the user turn off their camera to save upload bandwidth.
}
The older quality (1-100) and threshold fields are deprecated as of 0.23.0. Use networkState and networkStateReasons instead.

React to changes

Pass onNetworkQualityChange and onNetworkConnection to run side effects, such as toast notifications, when the network changes:
import { useCallback } from 'react';
import { useNetwork } from '@daily-co/daily-react';

useNetwork({
  onNetworkQualityChange: useCallback((event) => {
    if (event.networkState === 'bad') showToast('Your connection is unstable');
  }, []),
});

Detailed stats

For richer diagnostics, getStats() returns the latest network statistics (the same data as the daily-js getNetworkStats() method):
const { getStats } = useNetwork();
const stats = await getStats();

Topology

topology is 'peer', 'sfu', or 'none', telling you whether the call is peer-to-peer or routed through Daily’s SFU. This is informational; it changes automatically as the call scales. See video architecture for what drives it.

Monitor CPU load

A choppy call is often the device, not the network. useCPULoad reports whether Daily is under CPU pressure and why:
import { useCPULoad } from '@daily-co/daily-react';

function CPUWarning() {
  const { state, reason } = useCPULoad();
  // state: 'low' | 'high'; reason: 'none' | 'encode' | 'decode' | 'scheduleDuration'
  if (state !== 'high') return null;
  return <p>High CPU load ({reason}). Try closing other apps or lowering video quality.</p>;
}

Adapting to poor conditions

A common pattern: when the network is 'bad', reduce what you send or receive. Lower the published quality with useSendSettings, or reduce what you subscribe to with useReceiveSettings:
import { useEffect } from 'react';
import { useNetwork, useReceiveSettings } from '@daily-co/daily-react';

function AdaptiveQuality() {
  const { networkState } = useNetwork();
  const { updateReceiveSettings } = useReceiveSettings();

  useEffect(() => {
    if (networkState === 'bad') {
      updateReceiveSettings({ base: { video: { layer: 0 } } }); // lowest layer
    }
  }, [networkState, updateReceiveSettings]);

  return null;
}

Next steps

Rendering media

Render placeholders when video drops.

Video architecture

Peer-to-peer vs SFU, and what topology means.