Custom hook to interact with GraphQL
This hook could appear very useless with the advent of Apollo's client, and surely it is. I was playing around with this code some time ago when I started to integrate it into an old MVA / Twig-based app. I didn't get a direct connection with the graph server, for authentication problems, so I decided, instead of sending queries every time with Axios or another library, to write down this hook that I have used around the app.
import { useState, useEffect, useCallback, useMemo } from "react";
const useGraph = ({
query = ``,
graphServerURI = ``,
useNativeFetch,
fetcherFn
}) => {
if (!query) throw new Error("You should provide a query for graph");
if (!graphServerURI)
throw new Error("You should provide a server URI for graph");
if (!useNativeFetch && (!fetcherFn || typeof fetcherFn !== "function"))
throw new Error(
"If you are not using the native fetch method, please provide e fetcherFn"
);
const [graphdata, setState] = useState({});
const [errors, setGraphError] = useState(null);
const [loading, setLoading] = useState(false);
const nativeFecthOptions = useMemo(() => {
return (
useNativeFetch && {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
query: `${query}`
})
}
);
}, [query, useNativeFetch]);
const execute = useCallback(async () => {
setLoading(true);
let parsed, response;
try {
if (useNativeFetch) {
response = await fetch(graphServerURI, nativeFecthOptions);
parsed = await response.json();
} else {
parsed = await fetcherFn(graphServerURI, query);
fetcherFn(graphServerURI, query).then((result) => (parsed = result));
}
const { data, errors } = parsed;
if (errors) setGraphError(errors);
setState(data);
setLoading(false);
} catch (e) {
setGraphError(e);
}
}, [graphServerURI, fetcherFn, nativeFecthOptions, query, useNativeFetch]);
useEffect(() => {
execute();
}, [execute]);
return {
data: graphdata,
loading: loading,
errors: errors
};
};
If you use the useNativeFetch
param the hook will trigger a call using the fetch API, but if you want to use your custom function, you can pass it to fetcherFn
param.
Define your function, as an example called customFetcher.js
import ky from "ky";
export const customFetcher = (serverUrl, query) => {
return ky
.post(serverUrl, {
json: { query: query },
throwHttpErrors: false
})
.json();
}
Now in your function component, pass your function to fetcherFn
param.
import { customFetcher } from "./customFetcher";
const App = () => {
const query = `
query yourGraphQuery {
....
}
`
const { data, errors, loading } = useGraph({
query: query,
graphServerURI: '<http://yourgraphserver.example.com>',
useNativeFetch: false, // disable native fetch
fetcherFn: customFetcher // use your custom function
});
return ..... // your component with data
}