I’m new to React and Typescript and am learning about React hooks.
I however ran in to a problem which I don’t really understand/know how to fix.
Hook (for fetching data):
export const useFetch = <T>(
fetchFunc: () => Promise<Response>,
initialValue: T
) => {
const [value, setValue] = useState<T>(initialValue);
const fetchData = () =>
fetchFunc()
.then((res) => {
if (res.ok) return res;
throw new HttpFetchError(res);
})
.then(async (x) => await x.json())
.then((x) => setValue(x as T));
return [value, fetchData] as const;
};
I have a static class that fetches from the API (if called normally, everything is working fine here):
export class TestFetchClient {
static client?: HttpFetchClient;
static Init = (baseUrl?: string) =>
(this.client = new HttpFetchClient(baseUrl, "/api/"));
static async GetBored() {
if (this.client == null) throw new Error("Init first!");
return await this.client.Request({
request: "activity",
method: "GET",
});
}
// ...
}
When I try to use my useFetch hook I get the error in the function GetBored() that "this" is undefined when trying to access the initialized client. So I guess somehow the GetBored() method is called without the context of the Class or something. Can somebody explain this behavior and/or provide a solution so I can access my client variable in this situation?
Usage:
export default function SamplePage2() {
const [value, fetchValue] = useFetch(TestFetchClient.GetBored, {});
useEffect(() => {
// this throws the described error
fetchValue();
// this is working fine
TestFetchClient.GetBored().then((x) =>
x.json().then((y) => console.log(y))
);
}, []);
useEffect(() => {
console.log(value);
}, [value]);
return <h1>This is SamplePage 2</h1>;
}
Error message:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'client')
at GetBored (TestFetchClient.ts:10:1)
at fetchData (useFetch.ts:30:1)
at SamplePage2.tsx:12:1
2
Answers
As motto pointed out in his comment, I should not use "this" for static classes but the real class name. "this" shouldn't work here in the first place.
Solution:
I think you want something like this:
Then you’d have to alter your usage to be (note the call to Init so that it creates your HttpFetchClient):