React Usage Examples

Learn how to use the HTML to Image API in your React applications.

Basic Component Example

Here’s a React component that generates images from HTML:

import { useState } from 'react';

function ImageGenerator() {
  const [imageUrl, setImageUrl] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const generateImage = async () => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch('https://app.html2img.com/api/html', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.REACT_APP_HTML2IMG_API_KEY
        },
        body: JSON.stringify({
          html: `
            <div style="padding: 20px; background: #f0f0f0;">
              <h1>Hello from React!</h1>
              <p>Generated at ${new Date().toLocaleString()}</p>
            </div>
          `,
          width: 800,
          height: 600
        })
      });

      if (!response.ok) {
        throw new Error('Failed to generate image');
      }

      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      setImageUrl(url);
    } catch (error) {
      setError(error.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button 
        onClick={generateImage}
        disabled={loading}
      >
        {loading ? 'Generating...' : 'Generate Image'}
      </button>
      
      {error && (
        <div style={{ color: 'red' }}>
          Error: {error}
        </div>
      )}
      
      {imageUrl && (
        <div>
          <img 
            src={imageUrl} 
            alt="Generated content"
            style={{ maxWidth: '100%' }}
          />
        </div>
      )}
    </div>
  );
}

export default ImageGenerator;

Screenshot Component

Here’s a component for taking screenshots:

import { useState } from 'react';

function ScreenshotGenerator() {
  const [url, setUrl] = useState('https://example.com');
  const [imageUrl, setImageUrl] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const takeScreenshot = async () => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch('https://app.html2img.com/api/screenshot', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.REACT_APP_HTML2IMG_API_KEY
        },
        body: JSON.stringify({
          url,
          width: 1200,
          height: 800,
          dpi: 2,
          fullpage: true
        })
      });

      if (!response.ok) {
        throw new Error('Failed to take screenshot');
      }

      const blob = await response.blob();
      const newUrl = URL.createObjectURL(blob);
      setImageUrl(newUrl);
    } catch (error) {
      setError(error.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <div>
        <input
          type="text"
          value={url}
          onChange={(e) => setUrl(e.target.value)}
          placeholder="Enter URL"
          style={{ width: '100%', marginBottom: '1rem' }}
        />
      </div>
      
      <button 
        onClick={takeScreenshot}
        disabled={loading}
      >
        {loading ? 'Taking Screenshot...' : 'Take Screenshot'}
      </button>
      
      {error && (
        <div style={{ color: 'red', margin: '1rem 0' }}>
          Error: {error}
        </div>
      )}
      
      {imageUrl && (
        <div style={{ marginTop: '1rem' }}>
          <img 
            src={imageUrl} 
            alt="Screenshot"
            style={{ maxWidth: '100%' }}
          />
        </div>
      )}
    </div>
  );
}

export default ScreenshotGenerator;

Custom Hook Example

Here’s a custom hook to reuse the image generation logic:

import { useState, useCallback } from 'react';

function useHtml2Img() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const generateImage = useCallback(async (html, options = {}) => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await fetch('https://app.html2img.com/api/html', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.REACT_APP_HTML2IMG_API_KEY
        },
        body: JSON.stringify({
          html,
          width: options.width || 800,
          height: options.height || 600,
          ...options
        })
      });

      if (!response.ok) {
        throw new Error('Failed to generate image');
      }

      const blob = await response.blob();
      return URL.createObjectURL(blob);
    } catch (error) {
      setError(error.message);
      throw error;
    } finally {
      setLoading(false);
    }
  }, []);

  return {
    generateImage,
    loading,
    error
  };
}

// Usage Example
function MyComponent() {
  const { generateImage, loading, error } = useHtml2Img();
  const [imageUrl, setImageUrl] = useState(null);

  const handleGenerate = async () => {
    try {
      const url = await generateImage(`
        <div style="padding: 20px; background: #f0f0f0;">
          <h1>Hello from Custom Hook!</h1>
          <p>Generated at ${new Date().toLocaleString()}</p>
        </div>
      `);
      setImageUrl(url);
    } catch (error) {
      console.error('Failed to generate image:', error);
    }
  };

  return (
    <div>
      <button onClick={handleGenerate} disabled={loading}>
        Generate Image
      </button>
      {error && <div style={{ color: 'red' }}>Error: {error}</div>}
      {imageUrl && <img src={imageUrl} alt="Generated content" />}
    </div>
  );
}

Environment Setup

Make sure to set up your environment variables:

REACT_APP_HTML2IMG_API_KEY=your-api-key

For Vite-based React projects, use:

VITE_HTML2IMG_API_KEY=your-api-key

And access it with:

const apiKey = import.meta.env.VITE_HTML2IMG_API_KEY;

Never expose your API key in client-side code. Use environment variables and consider proxying requests through your backend.

Remember to clean up URLs created with URL.createObjectURL() when they’re no longer needed to prevent memory leaks:

useEffect(() => {
  return () => {
    if (imageUrl) {
      URL.revokeObjectURL(imageUrl);
    }
  };
}, [imageUrl]);