harshapitla/stackoverflow
0
1import { useCallback, useEffect, useRef, useState } from "react";2import { loadProductHuntCSV } from "../components/data/productHuntDataLoader";3 4const emptyMetadata = { rowsCount: 0, columns: [] };5 6const initialState = {7 status: "idle",8 rows: [],9 metadata: emptyMetadata,10 error: null,11};12 13export function useProductHuntDataset(datasetPath) {14 const [state, setState] = useState(initialState);15 const controllerRef = useRef(null);16 17 const computeMetadata = useCallback((rows) => {18 if (!Array.isArray(rows) || rows.length === 0) return emptyMetadata;19 const columnSet = new Set();20 let displayableCount = 0;21 rows.forEach((row) => {22 if (!row) return;23 Object.keys(row).forEach((key) => columnSet.add(key));24 const title = row.title ? String(row.title).trim() : "";25 if (title) {26 displayableCount += 1;27 }28 });29 return {30 rowsCount: displayableCount,31 columns: Array.from(columnSet),32 };33 }, []);34 35 const fetchRows = useCallback(async () => {36 controllerRef.current?.abort();37 const controller = new AbortController();38 controllerRef.current = controller;39 setState((prev) => ({ ...prev, status: "loading", error: null }));40 41 try {42 const { rows } = await loadProductHuntCSV(datasetPath, {43 signal: controller.signal,44 });45 if (controller.signal.aborted) return;46 setState({47 status: "success",48 rows,49 metadata: computeMetadata(rows),50 error: null,51 });52 } catch (err) {53 if (controller.signal.aborted) return;54 setState((prev) => ({55 ...prev,56 status: "error",57 error: err.message || "Failed to load data",58 }));59 }60 }, [datasetPath, computeMetadata]);61 62 useEffect(() => {63 fetchRows();64 }, [fetchRows]);65 66 const refetch = useCallback(() => {67 fetchRows();68 }, [fetchRows]);69 70 return { ...state, refetch };71}72 