In this step, we’ll implement Summary, which provide a concise, AI-generated summary to user queries. This feature is useful for delivering immediate insights to users without requiring them to sift through multiple search results.
To fetch a summary, use the Raffle API’s /summary endpoint. This requires a uid and a query parameter.
/summary
uid
query
Here’s the function to fetch a summary from the Raffle API:
export const fetchSummary = async (query) => { const response = await fetch( `https://api.raffle.ai/v2/summary?uid=$YOUR_RAFFLE_UID&query=${query}` ); const data = await response.json(); return data; };
This function sends a GET request to the summary endpoint using the user’s query and returns the summary response.
GET
summary
dangerouslySetInnerHTML
We’ll integrate the summary feature using React Query’s useMutation. This will handle the fetching of a summary dynamically when a search is triggered.
useMutation
import { useState } from "react"; import { useMutation } from "@tanstack/react-query"; import { fetchSummary } from "./api"; export const Search = () => { const [query, setQuery] = useState(""); const { data: summary, isPending: isLoadingSummary, mutate: handleFetchSummary, } = useMutation({ mutationKey: ["summary"], mutationFn: fetchSummary, }); const handleSearch = () => { if (query.trim()) { handleFetchSummary(query.trim()); } }; return ( <div> <h1>Search API - React Example</h1> <div> <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Enter your query..." /> <button onClick={handleSearch}>Search</button> </div> <div> <h2>Summary</h2> {isLoadingSummary ? ( <p>Loading...</p> ) : summary ? ( <div> <div dangerouslySetInnerHTML={{ __html: summary.summary }} /> {summary.references.length > 0 && ( <div> <h3>References</h3> <ul> {summary.references.map((ref) => ( <li key={ref.url}> <a href={ref.url} target="_blank" rel="noopener noreferrer" > {ref.title} </a> </li> ))} </ul> </div> )} </div> ) : ( <p>No summary available for this query.</p> )} </div> </div> ); };
fetchSummary
This step integrates the summary seamlessly into the UI, providing users with instant insights while maintaining a smooth and efficient experience.
At this stage, your full code should look like this:
import { useEffect, useState } from "react"; import { useMutation, useQuery } from "@tanstack/react-query"; import { useDebounce } from "@uidotdev/usehooks"; import { fetchSuggestions, fetchSummary, fetchTopQuestions } from "./api"; export const Search = () => { const [query, setQuery] = useState(""); const debouncedQuery = useDebounce(query, 500); // Debounce with 500ms delay const { data: topQuestions = [], isLoading } = useQuery({ queryKey: ["topQuestions"], queryFn: fetchTopQuestions, }); const { data: suggestions = [], mutate: handleFetchSuggestions } = useMutation({ mutationKey: ["suggestions", debouncedQuery], mutationFn: fetchSuggestions, }); const { data: summary, isPending: isLoadingSummary, mutate: handleFetchSummary, } = useMutation({ mutationKey: ["summary"], mutationFn: fetchSummary, }); // Trigger suggestions when debouncedQuery is at least 3 characters long useEffect(() => { if (debouncedQuery.length >= 3) { handleFetchSuggestions(debouncedQuery); } }, [debouncedQuery, handleFetchSuggestions]); const handleSearch = () => { if (query.trim()) { handleFetchSummary(query.trim()); } }; return ( <div> <h1>Search API - React Example</h1> <div> <input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Enter your query..." /> <button onClick={handleSearch}>Search</button> </div> <div> <h2>Top Questions</h2> {isLoading ? ( <p>Loading top questions...</p> ) : ( <ul> {topQuestions.map(({ question }) => ( <li key={question} onClick={() => setQuery(question)}> {question} </li> ))} </ul> )} </div> <div> <h2>Suggestions</h2> <ul> {suggestions.map(({ suggestion }, index) => ( <li key={index} onClick={() => { setQuery(suggestion); handleSearch(); }} > {suggestion} </li> ))} </ul> </div> <div> <h2>Summary</h2> {isLoadingSummary ? ( <p>Loading...</p> ) : summary ? ( <div> <div dangerouslySetInnerHTML={{ __html: summary.summary }} /> {summary.references.length > 0 && ( <div> <h3>References</h3> <ul> {summary.references.map((ref) => ( <li key={ref.url}> <a href={ref.url} target="_blank" rel="noopener noreferrer" > {ref.title} </a> </li> ))} </ul> </div> )} </div> ) : ( <p>No summary available for this query.</p> )} </div> <div> <h2>Search Results</h2> <p>Search results will appear here...</p> </div> </div> ); };
5 - Add Search Results