---
title: "React Hooks | Micdrop"
description: "React hooks for seamless integration of Micdrop voice conversations in React applications."
url: "https://micdrop.dev/docs/client/react-hooks"
---

*   [Getting Started](/docs/getting-started)
*   [Client (Browser)](/docs/client)
    
    *   [Installation](/docs/client/installation)
    *   [React Hooks](/docs/client/react-hooks)
    *   [Start/Stop Call](/docs/client/start-stop-call)
    *   [Pause/Resume Call](/docs/client/pause-resume-call)
    *   [Mute/Unmute Call](/docs/client/mute-unmute-call)
    *   [Call State](/docs/client/call-state)
    *   [Display Conversation Messages](/docs/client/display-conversation-messages)
    *   [Handling Tool Calls](/docs/client/handling-tool-calls)
    *   [Device Management](/docs/client/devices-management)
    *   [Voice Activity Detection (VAD)](/docs/client/vad)
    *   [Error Handling](/docs/client/error-handling)
    *   Utility Classes
        
        *   [Mic](/docs/client/utility-classes/mic)
        *   [MicdropClient](/docs/client/utility-classes/micdrop-client)
        *   [MicRecorder](/docs/client/utility-classes/mic-recorder)
        *   [Speaker](/docs/client/utility-classes/speaker)
        
    
*   [Server (Node.js)](/docs/server)
    
    *   [Installation](/docs/server/installation)
    *   [With Fastify](/docs/server/with-fastify)
    *   [With NestJS](/docs/server/with-nestjs)
    *   [Auth and Parameters](/docs/server/auth-and-parameters)
    *   [First Message](/docs/server/first-message)
    *   [Save Messages](/docs/server/save-messages)
    *   [Resume a Conversation](/docs/server/resume-conversation)
    *   [Recording Audio](/docs/server/recording-audio)
    *   [Error Handling](/docs/server/error-handling)
    *   [Tools](/docs/server/tools)
    *   [Extract Value from Answer](/docs/server/extract)
    *   [Auto End Call](/docs/server/auto-end-call)
    *   [Semantic Turn Detection](/docs/server/semantic-turn-detection)
    *   [Noise Filtering](/docs/server/noise-filtering)
    *   [Micdrop Protocol](/docs/server/protocol)
    
*   [AI Integrations](/docs/ai-integration)
    
    *   Provided Integrations
        
        *   [AI SDK](/docs/ai-integration/provided-integrations/ai-sdk)
        *   [Cartesia](/docs/ai-integration/provided-integrations/cartesia)
        *   [ElevenLabs](/docs/ai-integration/provided-integrations/elevenlabs)
        *   [Gladia](/docs/ai-integration/provided-integrations/gladia)
        *   [Gradium](/docs/ai-integration/provided-integrations/gradium)
        *   [Mistral](/docs/ai-integration/provided-integrations/mistral)
        *   [OpenAI](/docs/ai-integration/provided-integrations/openai)
        
    *   Custom Integrations
        
        *   [Agent (LLM)](/docs/ai-integration/custom-integrations/custom-agent)
        *   [Speech-to-Text (STT)](/docs/ai-integration/custom-integrations/custom-stt)
        *   [Text-to-Speech (TTS)](/docs/ai-integration/custom-integrations/custom-tts)
        
    *   Fallback Strategies
        
        *   [FallbackAgent](/docs/ai-integration/fallback-strategies/agent-fallback)
        *   [FallbackSTT](/docs/ai-integration/fallback-strategies/stt-fallback)
        *   [FallbackTTS](/docs/ai-integration/fallback-strategies/tts-fallback)
        
    *   [IA Vocale Souveraine 🇫🇷🇪🇺](/docs/ai-integration/sovereign-voice-ai)
    

[Micdrop](/) › [Documentation](/docs/getting-started)

# React Hooks

React hooks for seamless integration of Micdrop voice conversations in React applications.

## Installation

Terminal window

```
npm install @micdrop/react
```

## Quick Start

```
import { Micdrop } from '@micdrop/client'import { useMicdropState, useMicdropError } from '@micdrop/react'
function VoiceChat() {  const state = useMicdropState()
  return (    <div>      {state.isListening && <p>🎤 Listening...</p>}      {state.isProcessing && <p>🤔 Processing...</p>}      {state.isAssistantSpeaking && <p>🔊 Assistant speaking...</p>}    </div>  )}
```

## Available Hooks

### useMicdropState

Get the complete Micdrop state and subscribe to changes:

```
import { useMicdropState } from '@micdrop/react'
function CallStatus() {  const state = useMicdropState()
  return (    <div className="call-status">      <div className="status-row">        <span>Started:</span>        <span>{state.isStarted ? '✅' : '❌'}</span>      </div>
      <div className="status-row">        <span>Listening:</span>        <span>{state.isListening ? '🎤' : '🔇'}</span>      </div>
      <div className="status-row">        <span>Processing:</span>        <span>{state.isProcessing ? '🤔' : '⏳'}</span>      </div>
      <div className="status-row">        <span>Assistant Speaking:</span>        <span>{state.isAssistantSpeaking ? '🔊' : '🔇'}</span>      </div>    </div>  )}
```

### useMicdropError

Handle errors with a callback function:

```
import { useMicdropError } from '@micdrop/react'import { toast } from 'react-hot-toast'
function VoiceApp() {  useMicdropError((error) => {    switch (error.code) {      case 'Mic':        toast.error('Microphone error: Please check permissions')        break      case 'Connection':        toast.error('Connection lost: Trying to reconnect...')        break      case 'Unauthorized':        toast.error('Authentication failed: Please sign in')        break      default:        toast.error(`Error: ${error.message}`)    }  })
  return <div>Your voice app content...</div>}
```

### useMicdropEndCall

Handle call end events:

```
import { useMicdropEndCall } from '@micdrop/react'import { useRouter } from 'next/router'
function CallContainer() {  const router = useRouter()
  useMicdropEndCall(() => {    console.log('Call ended by assistant')
    // Navigate to end screen    router.push('/call-ended')  })
  return <div>Call in progress...</div>}
```

### useMicVolume

Monitor microphone volume levels:

```
import { useMicVolume } from '@micdrop/react'
function MicVolumeIndicator() {  const { micVolume, maxMicVolume } = useMicVolume()
  // Convert dB to 0-100 range  const normalizedVolume = Math.max(0, micVolume + 100)  const normalizedMax = Math.max(0, maxMicVolume + 100)
  return (    <div className="volume-indicator">      <div className="volume-label">Microphone</div>      <div className="volume-bar">        <div          className="volume-fill"          style={{ width: `${normalizedVolume}%` }}        />        <div className="volume-max" style={{ left: `${normalizedMax}%` }} />      </div>      <div className="volume-value">{Math.round(normalizedVolume)}</div>    </div>  )}
```

### useSpeakerVolume

Monitor speaker volume levels:

```
import { useSpeakerVolume } from '@micdrop/react'
function SpeakerVolumeIndicator() {  const { speakerVolume, maxSpeakerVolume } = useSpeakerVolume()
  const normalizedVolume = Math.max(0, speakerVolume + 100)  const normalizedMax = Math.max(0, maxSpeakerVolume + 100)
  return (    <div className="volume-indicator">      <div className="volume-label">Speaker</div>      <div className="volume-bar">        <div          className="volume-fill speaker"          style={{ width: `${normalizedVolume}%` }}        />      </div>      <div className="volume-value">{Math.round(normalizedVolume)}</div>    </div>  )}
```

## Component Examples

### Complete Call Component

```
import { useState } from 'react'import { Micdrop } from '@micdrop/client'import {  useMicdropState,  useMicdropError,  useMicdropEndCall,  useMicVolume,} from '@micdrop/react'
function VoiceCallComponent() {  const [serverUrl] = useState('ws://localhost:8081')  const state = useMicdropState()  const { micVolume } = useMicVolume()
  useMicdropError((error) => {    alert(`Error: ${error.message}`)  })
  useMicdropEndCall(() => {    alert('Call ended by assistant')  })
  const startCall = async () => {    try {      await Micdrop.start({        url: serverUrl,        vad: ['volume', 'silero'],      })    } catch (error) {      console.error('Failed to start call:', error)    }  }
  const stopCall = async () => {    await Micdrop.stop()  }
  const togglePause = () => {    if (state.isPaused) {      Micdrop.resume()    } else {      Micdrop.pause()    }  }
  const getStatusMessage = () => {    if (state.isStarting) return 'Starting call...'    if (state.isReconnecting) return '🔄 Reconnecting...'    if (state.isPaused) return '⏸️ Call paused'    if (state.isListening) return '🎤 Listening for your voice'    if (state.isProcessing) return '🤔 Processing your message'    if (state.isAssistantSpeaking) return '🔊 Assistant is speaking'    if (state.isStarted) return '✅ Call connected'    return 'Ready to start call'  }
  return (    <div className="voice-call">      <h2>Voice Assistant</h2>
      <div className="status">{getStatusMessage()}</div>
      <div className="controls">        {!state.isStarted ? (          <button onClick={startCall} disabled={state.isStarting}>            Start Call          </button>        ) : (          <>            <button onClick={togglePause}>              {state.isPaused ? 'Resume' : 'Pause'}            </button>            <button onClick={stopCall}>Stop Call</button>          </>        )}      </div>
      {state.isMicStarted && (        <div className="volume">          Mic Volume: {Math.max(0, micVolume + 100).toFixed(0)}        </div>      )}
      {state.conversation.length > 0 && (        <div className="conversation">          <h3>Conversation:</h3>          {state.conversation.map((message, index) => (            <div key={index} className={`message ${message.role}`}>              <strong>{message.role === 'user' ? 'You' : 'Assistant'}:</strong>              {message.content}            </div>          ))}        </div>      )}    </div>  )}
```

### Device Settings Component

```
import { useMicdropState } from '@micdrop/react'import { Micdrop } from '@micdrop/client'
function DeviceSettings() {  const state = useMicdropState()
  return (    <div className="device-settings">      <div className="device-group">        <label htmlFor="mic-select">Microphone:</label>        <select          id="mic-select"          value={state.micDeviceId || ''}          onChange={(e) => Micdrop.changeMicDevice(e.target.value)}        >          {state.micDevices.map((device) => (            <option key={device.deviceId} value={device.deviceId}>              {device.label || 'Unknown Device'}            </option>          ))}        </select>      </div>
      <div className="device-group">        <label htmlFor="speaker-select">Speaker:</label>        <select          id="speaker-select"          value={state.speakerDeviceId || ''}          onChange={(e) => Micdrop.changeSpeakerDevice(e.target.value)}        >          {state.speakerDevices.map((device) => (            <option key={device.deviceId} value={device.deviceId}>              {device.label || 'Unknown Device'}            </option>          ))}        </select>      </div>    </div>  )}
```

### Call Status Indicator

```
import { useMicdropState } from '@micdrop/react'
function CallStatusIndicator() {  const state = useMicdropState()
  const getStatus = () => {    if (state.error) {      return { icon: '❌', className: 'status-error', text: 'Error' }    }    if (state.isReconnecting) {      return {        icon: '🔄',        className: 'status-reconnecting',        text: 'Reconnecting',      }    }    if (state.isPaused) {      return { icon: '⏸️', className: 'status-paused', text: 'Paused' }    }    if (state.isUserSpeaking) {      return {        icon: '🗣️',        className: 'status-user-speaking',        text: 'User Speaking',      }    }    if (state.isListening) {      return { icon: '🎤', className: 'status-listening', text: 'Listening' }    }    if (state.isProcessing) {      return { icon: '🤔', className: 'status-processing', text: 'Processing' }    }    if (state.isAssistantSpeaking) {      return { icon: '🔊', className: 'status-speaking', text: 'Speaking' }    }    if (state.isStarted) {      return { icon: '✅', className: 'status-connected', text: 'Connected' }    }    return {      icon: '⭕',      className: 'status-disconnected',      text: 'Disconnected',    }  }
  const status = getStatus()
  return (    <div className={`status-indicator ${status.className}`}>      <span className="status-icon">{status.icon}</span>      <span className="status-text">{status.text}</span>    </div>  )}
```

## Custom Hooks

### Create Custom Hooks

Build your own hooks for specific needs:

```
import { useMicdropState } from '@micdrop/react'import { useEffect, useState } from 'react'
// Custom hook for call durationfunction useCallDuration() {  const state = useMicdropState()  const [duration, setDuration] = useState(0)
  useEffect(() => {    if (!state.isStarted) {      setDuration(0)      return    }
    const interval = setInterval(() => {      setDuration((d) => d + 1)    }, 1000)
    return () => clearInterval(interval)  }, [state.isStarted])
  return duration}
// Custom hook for conversation statsfunction useConversationStats() {  const state = useMicdropState()
  const stats = useMemo(() => {    const userMessages = state.conversation.filter((m) => m.role === 'user')    const assistantMessages = state.conversation.filter(      (m) => m.role === 'assistant'    )
    return {      totalMessages: state.conversation.length,      userMessages: userMessages.length,      assistantMessages: assistantMessages.length,      averageUserLength:        userMessages.reduce((sum, m) => sum + m.content.length, 0) /          userMessages.length || 0,      averageAssistantLength:        assistantMessages.reduce((sum, m) => sum + m.content.length, 0) /          assistantMessages.length || 0,    }  }, [state.conversation])
  return stats}
```

[Previous← Installation](/docs/client/installation)[NextStart/Stop Call →](/docs/client/start-stop-call)

On this page

*   [Installation](#installation)
*   [Quick Start](#quick-start)
*   [Available Hooks](#available-hooks)
*   [useMicdropState](#usemicdropstate)
*   [useMicdropError](#usemicdroperror)
*   [useMicdropEndCall](#usemicdropendcall)
*   [useMicVolume](#usemicvolume)
*   [useSpeakerVolume](#usespeakervolume)
*   [Component Examples](#component-examples)
*   [Complete Call Component](#complete-call-component)
*   [Device Settings Component](#device-settings-component)
*   [Call Status Indicator](#call-status-indicator)
*   [Custom Hooks](#custom-hooks)
*   [Create Custom Hooks](#create-custom-hooks)
