DEV Community

Apollo
Apollo

Posted on

How to integrate DeepSeek R1 into your React app

Integrating DeepSeek R1 into Your React Application: A Technical Deep Dive

DeepSeek R1 represents a significant leap in AI-powered search capabilities, offering semantic understanding and context-aware results. This tutorial will guide you through integrating DeepSeek R1 into a React application with proper authentication, query handling, and response rendering.

Prerequisites

Before beginning, ensure you have:

  • Node.js v16+
  • React 18+
  • A DeepSeek R1 API key (available from their developer portal)
  • Basic understanding of React hooks and async operations

Step 1: Setting Up the React Environment

First, create a new React project if you don't have one:

npx create-react-app deepseek-integration
cd deepseek-integration
Enter fullscreen mode Exit fullscreen mode

Install required dependencies:

npm install axios @tanstack/react-query
Enter fullscreen mode Exit fullscreen mode

Step 2: Creating the DeepSeek Service Layer

Create src/services/deepseek.js to encapsulate all API interactions:

import axios from 'axios';

const DEEPSEEK_API_URL = 'https://api.deepseek.com/v1/r1/search';
const API_KEY = process.env.REACT_APP_DEEPSEEK_API_KEY;

const deepseekClient = axios.create({
  baseURL: DEEPSEEK_API_URL,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  },
  timeout: 10000
});

export const search = async (query, options = {}) => {
  try {
    const response = await deepseekClient.post('', {
      query,
      max_results: options.maxResults || 5,
      filters: options.filters || {},
      context: options.context || null
    });
    return response.data;
  } catch (error) {
    console.error('DeepSeek API error:', error);
    throw error;
  }
};

export const batchSearch = async (queries) => {
  // Implementation for batch queries
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Implementing React Query for State Management

Create a custom hook in src/hooks/useDeepSeek.js:

import { useMutation, useQuery } from '@tanstack/react-query';
import { search, batchSearch } from '../services/deepseek';

export const useDeepSeekSearch = () => {
  return useMutation({
    mutationFn: ({ query, options }) => search(query, options),
    onError: (error) => {
      // Handle errors globally
      console.error('Search failed:', error);
    }
  });
};

export const useDeepSeekBatch = () => {
  return useMutation({
    mutationFn: (queries) => batchSearch(queries),
    // Additional configuration
  });
};
Enter fullscreen mode Exit fullscreen mode

Step 4: Building the Search Component

Create src/components/DeepSeekSearch.js:

import { useState } from 'react';
import { useDeepSeekSearch } from '../hooks/useDeepSeek';

const DeepSeekSearch = () => {
  const [query, setQuery] = useState('');
  const [options, setOptions] = useState({
    maxResults: 5,
    filters: {},
    context: null
  });

  const { mutate, data, isPending, error } = useDeepSeekSearch();

  const handleSearch = (e) => {
    e.preventDefault();
    if (query.trim()) {
      mutate({ query, options });
    }
  };

  return (
    <div className="deepseek-container">
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={query}
          onChange={(e) => setQuery(e.target.value)}
          placeholder="Enter your search query..."
        />
        <button type="submit" disabled={isPending}>
          {isPending ? 'Searching...' : 'Search'}
        </button>
      </form>

      {error && <div className="error">Error: {error.message}</div>}

      {data && (
        <div className="results">
          <h3>Search Results</h3>
          <ul>
            {data.results.map((result, index) => (
              <li key={index}>
                <h4>{result.title}</h4>
                <p>{result.snippet}</p>
                {result.metadata && (
                  <div className="metadata">
                    <span>Score: {result.score.toFixed(2)}</span>
                    <span>Source: {result.metadata.source}</span>
                  </div>
                )}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default DeepSeekSearch;
Enter fullscreen mode Exit fullscreen mode

Step 5: Advanced Features - Contextual Search

To implement contextual search (maintaining conversation context):

const [conversationContext, setConversationContext] = useState([]);

const handleContextualSearch = async (newQuery) => {
  const response = await mutate({
    query: newQuery,
    options: {
      context: conversationContext
    }
  });

  setConversationContext(prev => [
    ...prev,
    { role: 'user', content: newQuery },
    { role: 'assistant', content: response.summary }
  ]);
};
Enter fullscreen mode Exit fullscreen mode

Step 6: Performance Optimization

Implement debouncing for search inputs:

import { useCallback, useEffect, useState } from 'react';
import { useDeepSeekSearch } from '../hooks/useDeepSeek';

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
};

const OptimizedSearch = () => {
  const [query, setQuery] = useState('');
  const debouncedQuery = useDebounce(query, 500);
  const { mutate } = useDeepSeekSearch();

  useEffect(() => {
    if (debouncedQuery) {
      mutate({ query: debouncedQuery });
    }
  }, [debouncedQuery, mutate]);

  return <input value={query} onChange={(e) => setQuery(e.target.value)} />;
};
Enter fullscreen mode Exit fullscreen mode

Step 7: Error Handling and Retry Logic

Enhance the service layer with retry logic:

const searchWithRetry = async (query, options, retries = 3) => {
  try {
    return await search(query, options);
  } catch (error) {
    if (retries > 0 && error.response?.status >= 500) {
      await new Promise(resolve => setTimeout(resolve, 1000 * (4 - retries)));
      return searchWithRetry(query, options, retries - 1);
    }
    throw error;
  }
};
Enter fullscreen mode Exit fullscreen mode

Step 8: Implementing Result Caching

Add caching using React Query's built-in capabilities:

export const useCachedDeepSeekSearch = (query, options) => {
  return useQuery({
    queryKey: ['deepseek', query, options],
    queryFn: () => search(query, options),
    staleTime: 1000 * 60 * 5, // 5 minutes
    cacheTime: 1000 * 60 * 30, // 30 minutes
    enabled: !!query // Only run when query exists
  });
};
Enter fullscreen mode Exit fullscreen mode

Step 9: Type Safety with TypeScript (Optional)

For TypeScript users, create type definitions:

interface DeepSeekResult {
  id: string;
  title: string;
  snippet: string;
  url: string;
  score: number;
  metadata?: {
    source?: string;
    [key: string]: unknown;
  };
}

interface DeepSeekResponse {
  results: DeepSeekResult[];
  summary?: string;
  suggested_queries?: string[];
  query_time_ms: number;
}
Enter fullscreen mode Exit fullscreen mode

Step 10: Testing the Integration

Create comprehensive tests using Jest and React Testing Library:

import { render, screen, fireEvent } from '@testing-library/react';
import DeepSeekSearch from './DeepSeekSearch';
import { useDeepSeekSearch } from '../hooks/useDeepSeek';

jest.mock('../hooks/useDeepSeek');

describe('DeepSeekSearch', () => {
  it('should trigger search on form submission', async () => {
    const mockMutate = jest.fn();
    useDeepSeekSearch.mockReturnValue({
      mutate: mockMutate,
      data: null,
      isPending: false,
      error: null
    });

    render(<DeepSeekSearch />);

    const input = screen.getByPlaceholderText('Enter your search query...');
    const button = screen.getByRole('button', { name: 'Search' });

    fireEvent.change(input, { target: { value: 'test query' } });
    fireEvent.click(button);

    expect(mockMutate).toHaveBeenCalledWith({
      query: 'test query',
      options: expect.any(Object)
    });
  });
});
Enter fullscreen mode Exit fullscreen mode

Deployment Considerations

When deploying to production:

  1. Never expose your API key in client-side code
  2. Consider implementing a backend proxy
  3. Set appropriate CORS headers
  4. Implement rate limiting
  5. Monitor API usage and costs

Conclusion

This integration provides a robust foundation for incorporating DeepSeek R1's advanced search capabilities into your React application. The implementation includes:

  1. Service layer abstraction
  2. React Query for state management
  3. Contextual search support
  4. Performance optimizations
  5. Comprehensive error handling
  6. Type safety (optional)
  7. Testing framework

For advanced use cases, consider implementing:

  • Search result personalization
  • Multi-modal search (combining text with other media types)
  • Real-time search updates
  • Advanced analytics integration

Remember to consult the official DeepSeek R1 documentation for the most up-to-date API specifications and best practices.


🚀 Stop Writing Boilerplate Prompts

If you want to skip the setup and code 10x faster with complete AI architecture patterns, grab my Senior React Developer AI Cookbook ($19). It includes Server Action prompt libraries, UI component generation loops, and hydration debugging strategies.

Browse all 10+ developer products at the Apollo AI Store | Or snipe Solana tokens free via @ApolloSniper_Bot.

Top comments (0)