Overview

useIsTogether returns true when the user is currently connected to a React Together session, and false otherwise. This hook is essential for building connection-aware interfaces that adapt based on whether users are in a collaborative session.

Perfect for: Conditional rendering of collaborative features, connection status indicators, session-dependent logic, and graceful offline/online state handling.

Basic Usage

import { useIsTogether } from 'react-together'

function ConnectionStatus() {
  const isTogether = useIsTogether()
  
  return (
    <div>
      {isTogether ? (
        <span className="text-green-600">✓ Connected to session</span>
      ) : (
        <span className="text-gray-500">○ Not connected</span>
      )}
    </div>
  )
}

Signature

useIsTogether(): boolean

Return Value

isTogether
boolean

true if the user is connected to a React Together session, false otherwise

Examples

Session-Dependent Feature Toggle

Show different UI based on connection status:

import { useIsTogether, useStateTogether } from 'react-together'

function CollaborativeEditor() {
  const isTogether = useIsTogether()
  const [content, setContent] = useStateTogether('document', '')
  
  return (
    <div className="editor">
      <div className="status-bar">
        {isTogether ? (
          <span className="collaborative-mode">
            🤝 Collaborative Mode - Changes sync in real-time
          </span>
        ) : (
          <span className="offline-mode">
            📝 Offline Mode - Changes saved locally
          </span>
        )}
      </div>
      
      <textarea
        value={content}
        onChange={(e) => setContent(e.target.value)}
        placeholder={
          isTogether
            ? "Start typing to collaborate..."
            : "Connect to session to collaborate"
        }
        className={isTogether ? 'border-green-300' : 'border-gray-300'}
      />
      
      {!isTogether && (
        <div className="offline-notice">
          <p>Join a session to enable real-time collaboration</p>
          <button onClick={() => /* join session logic */ {}}>
            Join Session
          </button>
        </div>
      )}
    </div>
  )
}

Connection Status Dashboard

Build a comprehensive connection monitoring component:

import { useIsTogether, useConnectedUsers, useIsSynchronized } from 'react-together'

function SessionDashboard() {
  const isTogether = useIsTogether()
  const connectedUsers = useConnectedUsers()
  const isSynchronized = useIsSynchronized()
  
  if (!isTogether) {
    return (
      <div className="dashboard offline">
        <h3>📶 Session Status</h3>
        <div className="status-grid">
          <div className="status-item">
            <span className="label">Connection:</span>
            <span className="value disconnected">Disconnected</span>
          </div>
          <div className="status-item">
            <span className="label">Users:</span>
            <span className="value">0</span>
          </div>
          <div className="status-item">
            <span className="label">Sync Status:</span>
            <span className="value">N/A</span>
          </div>
        </div>
        
        <div className="actions">
          <button className="connect-btn">
            Connect to Session
          </button>
        </div>
      </div>
    )
  }
  
  return (
    <div className="dashboard online">
      <h3>📶 Session Status</h3>
      <div className="status-grid">
        <div className="status-item">
          <span className="label">Connection:</span>
          <span className="value connected">✓ Connected</span>
        </div>
        <div className="status-item">
          <span className="label">Users:</span>
          <span className="value">{connectedUsers.length}</span>
        </div>
        <div className="status-item">
          <span className="label">Sync Status:</span>
          <span className={`value ${isSynchronized ? 'synced' : 'syncing'}`}>
            {isSynchronized ? '✓ Synchronized' : '⏳ Synchronizing...'}
          </span>
        </div>
      </div>
      
      <div className="user-list">
        <h4>Connected Users:</h4>
        <ul>
          {connectedUsers.map(user => (
            <li key={user.userId} className={user.isYou ? 'me' : ''}>
              {user.nickname} {user.isYou && '(You)'}
            </li>
          ))}
        </ul>
      </div>
    </div>
  )
}

Smart Feature Loading

Conditionally load collaborative features only when connected:

import { Suspense, lazy } from 'react'
import { useIsTogether } from 'react-together'

// Lazy load collaborative components
const CollaborativeCursors = lazy(() => import('./CollaborativeCursors'))
const SharedCanvas = lazy(() => import('./SharedCanvas'))
const UserAvatars = lazy(() => import('./UserAvatars'))

function SmartCollaborativeApp() {
  const isTogether = useIsTogether()
  
  return (
    <div className="app">
      <header>
        <h1>My App</h1>
        {isTogether && (
          <Suspense fallback={<div>Loading collaboration features...</div>}>
            <UserAvatars />
          </Suspense>
        )}
      </header>
      
      <main>
        {isTogether ? (
          <Suspense fallback={<div>Loading shared workspace...</div>}>
            <SharedCanvas />
            <CollaborativeCursors />
          </Suspense>
        ) : (
          <div className="solo-workspace">
            <p>Working in solo mode</p>
            <button onClick={() => /* create session */ {}}>
              Start Collaborating
            </button>
          </div>
        )}
      </main>
    </div>
  )
}

Conditional Data Persistence

Handle data differently based on connection status:

import { useIsTogether, useStateTogether } from 'react-together'
import { useEffect, useState } from 'react'

function TodoApp() {
  const isTogether = useIsTogether()
  
  // Use shared state when connected, local state when offline
  const [sharedTodos, setSharedTodos] = useStateTogether('todos', [])
  const [localTodos, setLocalTodos] = useState([])
  
  const todos = isTogether ? sharedTodos : localTodos
  const setTodos = isTogether ? setSharedTodos : setLocalTodos
  
  // Save to localStorage when offline
  useEffect(() => {
    if (!isTogether) {
      localStorage.setItem('offline-todos', JSON.stringify(localTodos))
    }
  }, [localTodos, isTogether])
  
  // Load from localStorage when going offline
  useEffect(() => {
    if (!isTogether) {
      const saved = localStorage.getItem('offline-todos')
      if (saved) {
        setLocalTodos(JSON.parse(saved))
      }
    }
  }, [isTogether])
  
  const addTodo = (text: string) => {
    const newTodo = {
      id: Date.now().toString(),
      text,
      completed: false,
      createdAt: new Date().toISOString()
    }
    setTodos([...todos, newTodo])
  }
  
  return (
    <div className="todo-app">
      <div className="header">
        <h2>Todo List</h2>
        <div className="mode-indicator">
          {isTogether ? (
            <span className="collaborative">
              🤝 Collaborative Mode - {todos.length} shared todos
            </span>
          ) : (
            <span className="offline">
              💾 Offline Mode - {todos.length} local todos
            </span>
          )}
        </div>
      </div>
      
      <div className="todo-input">
        <input
          type="text"
          placeholder={
            isTogether
              ? "Add a shared todo..."
              : "Add a local todo..."
          }
          onKeyPress={(e) => {
            if (e.key === 'Enter' && e.currentTarget.value.trim()) {
              addTodo(e.currentTarget.value.trim())
              e.currentTarget.value = ''
            }
          }}
        />
      </div>
      
      <ul className="todo-list">
        {todos.map(todo => (
          <li key={todo.id} className={todo.completed ? 'completed' : ''}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={(e) => {
                const updated = todos.map(t =>
                  t.id === todo.id ? { ...t, completed: e.target.checked } : t
                )
                setTodos(updated)
              }}
            />
            <span>{todo.text}</span>
            {!isTogether && (
              <small className="offline-badge">Local</small>
            )}
          </li>
        ))}
      </ul>
      
      {!isTogether && todos.length > 0 && (
        <div className="sync-prompt">
          <p>You have {todos.length} local todos</p>
          <button onClick={() => /* sync to session */ {}}>
            Join Session to Share
          </button>
        </div>
      )}
    </div>
  )
}

Progressive Enhancement Pattern

Enhance basic functionality with collaborative features:

import { useIsTogether, useConnectedUsers, useCursors } from 'react-together'

function ProgressiveCollaborativeForm() {
  const isTogether = useIsTogether()
  const connectedUsers = useConnectedUsers()
  const cursors = useCursors()
  
  return (
    <div className="form-container" style={{ position: 'relative' }}>
      <form className="contact-form">
        <h2>Contact Form</h2>
        
        {/* Basic form works offline */}
        <div className="field">
          <label htmlFor="name">Name</label>
          <input
            id="name"
            type="text"
            placeholder="Your name"
          />
        </div>
        
        <div className="field">
          <label htmlFor="email">Email</label>
          <input
            id="email"
            type="email"
            placeholder="[email protected]"
          />
        </div>
        
        <div className="field">
          <label htmlFor="message">Message</label>
          <textarea
            id="message"
            placeholder="Your message..."
            rows={4}
          />
        </div>
        
        <button type="submit">
          Send Message
        </button>
      </form>
      
      {/* Enhanced with collaborative features when connected */}
      {isTogether && (
        <>
          {/* Show live cursors */}
          {Object.entries(cursors).map(([userId, position]) => (
            <div
              key={userId}
              className="cursor"
              style={{
                position: 'absolute',
                left: position.x,
                top: position.y,
                pointerEvents: 'none',
                zIndex: 1000
              }}
            >
              <div className="cursor-pointer"></div>
              <div className="cursor-label">
                {connectedUsers.find(u => u.userId === userId)?.nickname}
              </div>
            </div>
          ))}
          
          {/* Collaboration status */}
          <div className="collaboration-status">
            <p>
              ✨ Enhanced with real-time collaboration
            </p>
            <p>
              {connectedUsers.length} user(s) can see your cursor movements
            </p>
          </div>
        </>
      )}
    </div>
  )
}

Best Practices

Connection State Management

import { useIsTogether } from 'react-together'
import { useEffect, useState } from 'react'

function useConnectionHistory() {
  const isTogether = useIsTogether()
  const [connectionHistory, setConnectionHistory] = useState<Array<{
    timestamp: Date
    status: 'connected' | 'disconnected'
  }>>([])
  
  useEffect(() => {
    setConnectionHistory(prev => [
      ...prev,
      {
        timestamp: new Date(),
        status: isTogether ? 'connected' : 'disconnected'
      }
    ])
  }, [isTogether])
  
  return { isTogether, connectionHistory }
}

Graceful Degradation

import { useIsTogether } from 'react-together'

function useCollaborativeFeatures() {
  const isTogether = useIsTogether()
  
  return {
    // Enable features based on connection
    showCursors: isTogether,
    enableRealTimeSync: isTogether,
    showUserList: isTogether,
    allowSessionSharing: isTogether,
    
    // Provide fallbacks
    saveStrategy: isTogether ? 'realtime' : 'localStorage',
    notificationLevel: isTogether ? 'minimal' : 'verbose'
  }
}

Common Patterns

  • Feature Flags: Use as a feature flag for collaborative functionality
  • Progressive Enhancement: Start with basic features, enhance when connected
  • Conditional Rendering: Show different UI based on connection status
  • Data Strategy: Switch between shared and local data based on connection
  • Performance: Avoid loading collaborative features when not needed

TypeScript Support

useIsTogether is fully typed and returns a boolean value:

import { useIsTogether } from 'react-together'

const isTogether: boolean = useIsTogether()

Technical Notes

useIsTogether is an alias for useIsJoined from @multisynq/react. It returns true when the user has successfully joined a session and the connection is active.

Connection status can change during the session due to network issues. Always handle both connected and disconnected states gracefully in your UI.