useMentions

Overview

The useMentions hook provides comprehensive mention functionality for text inputs. It automatically detects @mentions in text, fetches user suggestions, manages mention state, and handles mention selection. This hook is designed to work with text input components that need full mention support.

Usage Example

import { useMentions } from "@replyke/react-js";
import { useState, useRef } from "react";
 
function CommentInput() {
  const [content, setContent] = useState("");
  const [cursorPosition, setCursorPosition] = useState(0);
  const [isSelectionActive, setIsSelectionActive] = useState(false);
  const inputRef = useRef<HTMLTextAreaElement>(null);
 
  const focus = () => {
    inputRef.current?.focus();
  };
 
  const {
    isMentionActive,
    loading,
    mentionSuggestions,
    handleMentionClick,
    mentions,
    addMention,
    resetMentions,
  } = useMentions({
    content,
    setContent,
    focus,
    cursorPosition,
    isSelectionActive,
  });
 
  const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setContent(e.target.value);
    setCursorPosition(e.target.selectionStart);
  };
 
  const handleSelectionChange = () => {
    if (inputRef.current) {
      const start = inputRef.current.selectionStart;
      const end = inputRef.current.selectionEnd;
      setCursorPosition(start);
      setIsSelectionActive(start !== end);
    }
  };
 
  return (
    <div>
      <textarea
        ref={inputRef}
        value={content}
        onChange={handleTextChange}
        onSelect={handleSelectionChange}
        onKeyUp={handleSelectionChange}
        onMouseUp={handleSelectionChange}
        placeholder="Type @ to mention someone..."
      />
 
      {isMentionActive && (
        <div className="mention-suggestions">
          {loading ? (
            <div>Loading suggestions...</div>
          ) : (
            mentionSuggestions.map((user) => (
              <div
                key={user.id}
                onClick={() => handleMentionClick(user)}
                className="mention-suggestion"
              >
                @{user.username} - {user.name}
              </div>
            ))
          )}
        </div>
      )}
 
      <div>
        <strong>Current mentions:</strong>
        {mentions.map((mention) => (
          <span key={mention.id}>@{mention.username} </span>
        ))}
      </div>
    </div>
  );
}

Parameters & Returns

Required Props

The hook requires the following props to function:

ParameterTypeRequiredDescription
contentstringYesThe current text content being edited
setContent(value: string) => voidYesFunction to update the text content
focus() => voidYesFunction to focus the text input
cursorPositionnumberYesCurrent cursor position in the text
isSelectionActivebooleanYesWhether text selection is currently active

Return Values

The hook returns an object with the following properties:

PropertyTypeDescription
isMentionActivebooleanWhether mention suggestions are currently active
loadingbooleanWhether user suggestions are being fetched
mentionSuggestionsUser[]Array of suggested users for mention
handleMentionClick(user: User) => voidFunction to handle clicking a mention suggestion
mentionsMention[]Array of current mentions in the text
addMention(user: User) => voidFunction to manually add a mention
resetMentions() => voidFunction to clear all mentions and reset state

Type Definitions

interface Mention {
  id: string;
  username: string;
}

Behavior & Features

Automatic Mention Detection

  • Detects when user types @ followed by 3+ characters
  • Only activates when there’s no active text selection
  • Uses regex pattern /^@[\w.]+$/ to validate mention triggers
  • Supports usernames with letters, numbers, underscores, and dots
  • Implements 1-second debounce to avoid excessive API calls
  • Automatically fetches user suggestions based on typed query
  • Clears suggestions when mention pattern no longer matches

State Management

  • Tracks all mentions added to the text
  • Prevents duplicate mentions for the same user
  • Maintains mention list independent of text content
  • Provides functions to manually manage mention state

Text Replacement

  • Automatically replaces mention trigger with selected username
  • Maintains proper spacing after mention insertion
  • Focuses back to input after mention selection

Integration Requirements

To use this hook effectively, your text input component must:

  1. Track cursor position: Update cursorPosition on text changes and cursor movements
  2. Track selection state: Monitor whether text is selected vs just cursor positioned
  3. Provide focus function: Allow the hook to refocus the input after mention selection
  4. Handle content updates: Use the provided setContent function for text updates

Advanced Usage

Custom Mention Validation

// The hook automatically validates mentions, but you can access
// the current mentions array for additional processing
const { mentions } = useMentions(props);
 
// Process mentions for API submission
const mentionData = mentions.map(mention => ({
  userId: mention.id,
  username: mention.username,
}));

Manual Mention Management

const { addMention, resetMentions } = useMentions(props);
 
// Manually add a mention (e.g., from external user selection)
const handleAddUser = (user: User) => {
  addMention(user);
};
 
// Clear all mentions (e.g., on form reset)
const handleClearForm = () => {
  resetMentions();
  setContent("");
};