feat: ApiContext

This commit is contained in:
2026-06-02 13:17:58 +07:00
parent 25c9bc21b3
commit 1797af7ba9
8 changed files with 4444 additions and 4262 deletions
+39
View File
@@ -0,0 +1,39 @@
import React, { createContext, useContext } from "react";
// Sentinel value to reliably detect if the hook is called outside the provider
const sentinel = {};
/**
* ApiContext created using the React Context API.
* Defaults to a sentinel value to detect out-of-provider usage.
*/
export const ApiContext = createContext(sentinel);
/**
* ApiProvider component that accepts a `headers` prop and provides it through context.
*
* @param {Object} props
* @param {Object} props.headers - The headers to provide to API requests
* @param {React.ReactNode} props.children - Child components
*/
export function ApiProvider({ headers, children }) {
return React.createElement(
ApiContext.Provider,
{ value: headers },
children
);
}
/**
* Custom hook `useApiHeaders()` that returns the current headers from context.
* Throws a clear error if called outside of `ApiProvider`.
*
* @returns {Object} The current headers from context
*/
export function useApiHeaders() {
const context = useContext(ApiContext);
if (context === sentinel) {
throw new Error("useApiHeaders must be used within an ApiProvider");
}
return context;
}
+9 -10
View File
@@ -16,6 +16,7 @@ import {
import ClearIcon from "@mui/icons-material/Clear";
import FilterTableBuilder from "../utils/filterTableBuilder";
import { apiRequest } from "../api/request";
import { useApiHeaders } from "./ApiContext";
export default function ListVirtual({
id,
@@ -33,8 +34,8 @@ export default function ListVirtual({
helperText,
filter,
isApiGo = false,
headersRequest,
}) {
const headersRequest = useApiHeaders();
const [open, setOpen] = useState(false);
const [search, setSearch] = useState("");
const [rows, setRows] = useState([]);
@@ -65,18 +66,17 @@ export default function ListVirtual({
if (keyword) payload.like(name, keyword);
if (filter && filter.length > 0) {
filter.forEach(f => payload.where(f.logic_operator || "=", f.name, f.value, f.operator || "AND", f.value1 || null, f.table_name || null));
filter.forEach(f => payload.where(f.logic_operator || "=", f.name, f.value, f.operator || "AND", f.value1 || null, f.table_name || null));
}
try {
const res = await apiRequest.search(
url,
payload.build(),
{},
{
isApiGo,
headers: headersRequest
}
},
isApiGo,
);
const incomingData = res.data || [];
@@ -125,14 +125,13 @@ export default function ListVirtual({
.equal("id", id);
try {
const res = await apiRequest.search(
url,
const res = await apiRequest.search(
url,
payload.build(),
{},
{
isApiGo,
headers: headersRequest
}
},
isApiGo,
);
const data = res.data?.[0];
+2
View File
@@ -0,0 +1,2 @@
export { default as ListVirtual } from "./ListVirtual";
export * from "./ApiContext";