Updated useData hook

This commit is contained in:
Jose
2026-02-15 03:00:14 +01:00
parent 58f994d58f
commit cee625334c

View File

@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback, useRef } from "react"; import { useState, useEffect, useCallback, useRef } from "react";
import axios from "axios"; import axios from "axios";
export const useData = (config) => { export const useData = (config, onError) => {
const [data, setData] = useState(null); const [data, setData] = useState(null);
const [dataLoading, setLoading] = useState(true); const [dataLoading, setLoading] = useState(true);
const [dataError, setError] = useState(null); const [dataError, setError] = useState(null);
@@ -13,10 +13,59 @@ export const useData = (config) => {
} }
}, [config]); }, [config]);
const getAuthHeaders = () => ({ const getAuthHeaders = (isFormData = false) => {
"Content-Type": "application/json", const token = localStorage.getItem("token");
"Authorization": `Bearer ${localStorage.getItem("token")}`,
}); const headers = {};
if (token) headers.Authorization = `Bearer ${token}`;
if (!isFormData) {
headers["Content-Type"] = "application/json";
}
return headers;
};
const handleAxiosError = (err) => {
if (err.response && err.response.data) {
const data = err.response.data;
if (data.status === 422 && data.errors) {
return {
status: 422,
errors: data.errors,
path: data.path ?? null,
timestamp: data.timestamp ?? null,
};
}
return {
status: data.status ?? err.response.status,
error: data.error ?? null,
message: data.message ?? err.response.statusText ?? "Error desconocido",
path: data.path ?? null,
timestamp: data.timestamp ?? null,
};
}
if (err.request) {
return {
status: null,
error: "Network Error",
message: "No se pudo conectar al servidor",
path: null,
timestamp: new Date().toISOString(),
};
}
return {
status: null,
error: "Client Error",
message: err.message || "Error desconocido",
path: null,
timestamp: new Date().toISOString(),
};
};
const fetchData = useCallback(async () => { const fetchData = useCallback(async () => {
const current = configRef.current; const current = configRef.current;
@@ -30,101 +79,62 @@ export const useData = (config) => {
headers: getAuthHeaders(), headers: getAuthHeaders(),
params: current.params, params: current.params,
}); });
setData(response.data.data); setData(response.data);
} catch (err) { } catch (err) {
setError(err.response?.data?.message || err.message); const error = handleAxiosError(err);
setError(error);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
if (config?.baseUrl) { if (config?.baseUrl) fetchData();
fetchData();
}
}, [config, fetchData]); }, [config, fetchData]);
const getData = async (url, params = {}) => { const requestWrapper = async (method, endpoint, payload = null, refresh = false) => {
try { try {
const response = await axios.get(url, { const isFormData = payload instanceof FormData;
headers: getAuthHeaders(), const headers = getAuthHeaders(isFormData);
params, const cfg = { headers };
}); let response;
return { data: response.data.data, error: null };
if (method === "get") {
if (payload) cfg.params = payload;
response = await axios.get(endpoint, cfg);
} else if (method === "delete") {
if (payload) cfg.data = payload;
response = await axios.delete(endpoint, cfg);
} else {
response = await axios[method](endpoint, payload, cfg);
}
if (refresh) await fetchData();
return response.data;
} catch (err) { } catch (err) {
return { const error = handleAxiosError(err);
data: null,
error: err.response?.data?.message || err.message, if (error.status !== 422 && onError) {
}; onError(error);
}
setError(error);
throw error;
} }
}; };
const postData = async (endpoint, payload) => { const clearError = () => setError(null);
const headers = {
Authorization: `Bearer ${localStorage.getItem("token")}`,
...(payload instanceof FormData ? {} : { "Content-Type": "application/json" }),
};
const response = await axios.post(endpoint, payload, { headers });
await fetchData();
return response.data.data;
};
const postDataValidated = async (endpoint, payload) => {
try {
const headers = {
Authorization: `Bearer ${localStorage.getItem("token")}`,
...(payload instanceof FormData ? {} : { "Content-Type": "application/json" }),
};
const response = await axios.post(endpoint, payload, { headers });
return { data: response.data.data, errors: null };
} catch (err) {
const raw = err.response?.data?.message;
let parsed = {};
try {
parsed = JSON.parse(raw);
} catch {
return { data: null, errors: { general: raw || err.message } };
}
return { data: null, errors: parsed };
}
};
const putData = async (endpoint, payload) => {
const response = await axios.put(endpoint, payload, {
headers: getAuthHeaders(),
});
await fetchData();
return response.data.data;
};
const deleteData = async (endpoint) => {
const response = await axios.delete(endpoint, {
headers: getAuthHeaders(),
});
await fetchData();
return response.data.data;
};
const deleteDataWithBody = async (endpoint, payload) => {
const response = await axios.delete(endpoint, {
headers: getAuthHeaders(),
data: payload,
});
await fetchData();
return response.data.data;
};
return { return {
data, data,
dataLoading, dataLoading,
dataError, dataError,
getData, clearError,
postData, getData: (url, params, refresh = true) => requestWrapper("get", url, params, refresh),
postDataValidated, postData: (url, body, refresh = true) => requestWrapper("post", url, body, refresh),
putData, putData: (url, body, refresh = true) => requestWrapper("put", url, body, refresh),
deleteData, deleteData: (url, refresh = true) => requestWrapper("delete", url, null, refresh),
deleteDataWithBody, deleteDataWithBody: (url, body, refresh = true) => requestWrapper("delete", url, body, refresh)
}; };
}; };