Skip to main content

Overview

The useBlockData hook provides a convenient way to access block data for a specific block ID. It’s a shorthand for accessing editor.children[blockId].

Usage

import { useBlockData } from '@yoopta/editor';

function BlockInfo({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);

  if (!block) return null;

  return (
    <div>
      <p>Type: {block.type}</p>
      <p>Order: {block.meta.order}</p>
      <p>Depth: {block.meta.depth}</p>
    </div>
  );
}

Signature

function useBlockData(blockId: string): YooptaBlockData | undefined

Parameters

blockId
string
required
The unique identifier of the block to retrieve

Returns

YooptaBlockData | undefined - The block data object, or undefined if not found

Block Data Structure

The returned block data has the following structure:
type YooptaBlockData = {
  id: string;              // Unique block identifier
  type: string;            // Block type (e.g., "Paragraph", "HeadingOne")
  value: SlateElement[];   // Slate element array
  meta: {
    order: number;         // Position in document
    depth: number;         // Nesting level (0 = root)
    align?: 'left' | 'center' | 'right';  // Text alignment
  };
}

Examples

Display Block Metadata

function BlockMetadata({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);

  if (!block) {
    return <div>Block not found</div>;
  }

  return (
    <div>
      <h3>Block Information</h3>
      <ul>
        <li>ID: {block.id}</li>
        <li>Type: {block.type}</li>
        <li>Position: {block.meta.order}</li>
        <li>Depth: {block.meta.depth}</li>
        {block.meta.align && <li>Alignment: {block.meta.align}</li>}
      </ul>
    </div>
  );
}

Conditional Rendering Based on Block Type

function BlockTypeIndicator({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);

  if (!block) return null;

  const isHeading = block.type.startsWith('Heading');
  const isParagraph = block.type === 'Paragraph';

  return (
    <div>
      {isHeading && <span>📰 Heading</span>}
      {isParagraph && <span>📝 Paragraph</span>}
    </div>
  );
}

Access Block Content

function BlockContentLength({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);

  if (!block) return null;

  const element = block.value[0];
  const textContent = element?.children
    ?.map(child => 'text' in child ? child.text : '')
    .join('');

  return (
    <div>
      Content length: {textContent?.length || 0} characters
    </div>
  );
}

Check Block Nesting

function BlockNestingIndicator({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);

  if (!block) return null;

  const nestingLevel = block.meta.depth;
  const isNested = nestingLevel > 0;

  return (
    <div style={{ marginLeft: `${nestingLevel * 20}px` }}>
      {isNested && `↳ Nested (Level ${nestingLevel})`}
      {!isNested && 'Root level'}
    </div>
  );
}

Use Cases

  • Custom UI Components: Display block metadata or custom controls
  • Conditional Rendering: Show/hide UI based on block type or state
  • Block Analytics: Track block usage and patterns
  • Custom Toolbars: Build block-specific toolbars
  • Validation: Check block properties before operations

Performance Considerations

This hook accesses the editor context, so it will re-render when the editor state changes. For performance-critical components, consider:
  • Memoizing derived values with useMemo
  • Using React.memo to prevent unnecessary re-renders
  • Extracting only the data you need
function OptimizedBlockInfo({ blockId }: { blockId: string }) {
  const block = useBlockData(blockId);
  
  // Memoize derived values
  const blockType = useMemo(() => block?.type, [block?.type]);
  const blockOrder = useMemo(() => block?.meta.order, [block?.meta.order]);

  return (
    <div>
      <span>Type: {blockType}</span>
      <span>Order: {blockOrder}</span>
    </div>
  );
}

See Also

Build docs developers (and LLMs) love