typescript “this”在静态方法中未定义

pxy2qtax  于 2023-04-22  发布在  TypeScript
关注(0)|答案(2)|浏览(159)

我是React和Typescript的新手,正在学习React hooks。然而,我遇到了一个问题,我真的不知道如何解决。
钩子(用于获取数据):

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;
};

我有一个从API获取的静态类(如果正常调用,这里一切正常):

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",
        });
    }
    // ...
}

当我尝试使用我的useFetch钩子时,我在GetBored()函数中得到错误,即在尝试访问初始化的客户端时,“this”未定义。所以我猜不知何故,GetBored()方法被调用时没有类的上下文或其他内容。有人能解释这种行为和/或提供一个解决方案,以便我可以在这种情况下访问我的客户端变量吗?
使用方法:

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>;
}

错误信息:

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
6jjcrrmo

6jjcrrmo1#

我想你想要这样的东西:

export class TestFetchClient {
    static client?: HttpFetchClient;

    static Init = (baseUrl?: string) =>
        (TestFetchClient.client = new HttpFetchClient(baseUrl, "/api/"));

    static async GetBored() {
        if (TestFetchClient.client == null) throw new Error("Init first!");

        return await this.client.Request({
            request: "activity",
            method: "GET",
        });
    }
    // ...
}

然后你必须改变你的用法为(注意调用Init,这样它就创建了你的HttpFetchClient):

export default function SamplePage2() {
    const [value, fetchValue] = useFetch(TestFetchClient.GetBored, {});

    useEffect(() => {
        // this throws the described error
        fetchValue();

        // this is working fine
        TestFetchClient.Init().GetBored().then((x) =>
            x.json().then((y) => console.log(y))
        );
    }, []);

    useEffect(() => {
        console.log(value);
    }, [value]);

    return <h1>This is SamplePage 2</h1>;
}
vohkndzv

vohkndzv2#

正如motto在他的评论中指出的那样,我不应该在静态类中使用“this”,而应该使用真实的的类名。
解决方案:

export class TestFetchClient {
    static client?: HttpFetchClient;

    static Init = (baseUrl?: string) =>
        (HttpFetchClient.client = new HttpFetchClient(baseUrl, "/api/"));

    static async GetBored() {
        if (HttpFetchClient.client == null) throw new Error("Init first!");

        return await HttpFetchClient.client.Request({
            request: "activity",
            method: "GET",
        });
    }
    // ...
}

相关问题