当前位置: 首页 > 知识库问答 >
问题:

在setState中使用异步等待

池赞
2023-03-14

我想进行一个基于当前状态的API调用,但不能使setState函数作为异步函数工作。

    handlePage = (direction: number) => {
    this.setState( async (state) => {
        const tickets: Ticket[] = await api.getTickets(`?page=${state.pageNum + direction}`)
        const pageNum: number = state.pageNum + direction;
        return { pageNum, tickets };
    });
}

给我错误:

类型为“”的参数(状态:只读)=

如果我在setState方法之外获取数据,它会起作用,但我害怕对过时的页码进行API调用

    handlePage = async (direction: number) => {
    const tickets: Ticket[] = await api.getTickets(`?page=${this.state.pageNum + direction}`)
    this.setState( (state) => {
        const pageNum: number = state.pageNum + direction;
        return { pageNum, tickets };
    });
}

共有2个答案

汲利
2023-03-14

setState只执行作业设置状态(并触发重新渲染:P);我认为您可以将功能更改为:

handlePage = async (direction: number) => {
    const tickets: Ticket[] = await api.getTickets(`?page=${this.state.pageNum + direction}`);
    
    this.setState({
        pageNum: this.state.pageNum + direction,
        tickets
    })
}
宇文迪
2023-03-14

有很多方法可以解决这个问题。我同意这是一个XY问题,因为我的建议是重新构造它,这样你就不会有这个问题。

我的最佳建议是,您所在的州将所有以前加载的页面的票证存储在由页码键入的数组中。

pageNum更改时,您(有条件地)获取该页的结果。每个响应都知道它在状态中属于哪里,所以在存储它时,这是否仍然是当前页面并不重要。如果pageNum在快速连续更改两次,您将执行两个调用并存储两个结果,但不会混淆哪一个是正确的结果,因为每个结果都与其页码相关联。

访问当前页面的票证时,只需在票证数组中查找当前页码。它将是一个数组票证[]未定义,如果它仍在加载。这是你以前没有的额外信息,因为之前你不知道你正在展示的票是当前的还是上一页的剩余。

另一个好处是,如果用户在页面之间来回移动,则不需要重复API调用。在获取之前,您可以检查是否已经有该页面的数据。

import React from "react";

interface Ticket {
    // actual properties
}

interface State {
    tickets: Record<number, Ticket[] | undefined>;
    pageNum: number;
}

class MyComponent extends React.Component<{}, State> {
    state: State = {
        tickets: {},
        pageNum: 1,
    }

    handlePage = async (direction: number) => {
        const page = this.state.pageNum + direction;
        // can skip the API call if already loaded!
        if (this.state.tickets[page] !== undefined) {
            return;
        }
        const tickets: Ticket[] = await api.getTickets(`?page=${page}`);
        // we will use the prevState when saving the tickets
        this.setState(prevState => ({
            tickets: {
                ...prevState.tickets,
                [page]: tickets
            }
        }));
    }

    render() {
        // get the tickets for the current page
        const tickets = this.state.tickets[this.state.pageNum] ?? [];
        // might also want to distinguish between an empty result and an incomplete fetch
        const isLoading = this.state.tickets[this.state.pageNum] === undefined;

        return <div/>
    }
}
 类似资料:
  • 问题内容: 我有调度动作的功能。我想在操作之前和之后显示一个加载程序。我知道将对象传递给时会做出反应。问题是如何以异步方式更新属性: 基本上,如果我将此属性作为应用程序状态的一部分(使用Redux),那么一切都很好,但是我真的更喜欢将此属性仅带到组件状态。 问题答案: 将其余代码包装在第一个的回调中: 有了这个,你可以保证被设定为之前被调用,并且被设置回。 这假设您的功能是同步的。如果不是,则将其

  • 问题内容: 我认为节点7.4支持异步/等待,但是此示例不起作用: 结果是: 如何在节点7.4上使用异步/等待? 问题答案: 是的,Node.js v7支持async-await,但将其锁定在标志后面。尚未准备就绪的功能不在此标记后面。 要在Node.js v7中使用async-await,只需使用此标志运行Node服务- async-await的正式发行版预定于4月启动的Node.js v8。 您

  • 我以为async/wait在节点7.4中得到了支持,但是这个例子不起作用: 结果: 如何在node 7.4中使用async/await?

  • 问题内容: 在循环中使用/ 是否有任何问题?我试图遍历文件数组和每个文件的内容。 这段代码确实有效,但是这可能会出问题吗?我让某人告诉我,您不应该在这样的高阶函数中使用/ ,所以我只是想问一下这是否有问题。 问题答案: 确保代码确实有效,但是我很确定它不会实现您期望的功能。它只会触发多个异步调用,但此后函数会立即返回。 顺序阅读 如果要顺序读取文件, 则不能使用。只需使用现代循环即可,该循环将按预

  • 问题内容: 示例了如何使用内置的加密库和流来计算文件的md5。 但是是否可以将其转换为使用ES8异步/等待而不是使用上述回调,但仍保持使用流的效率? 问题答案: / 仅适用于promise,不适用于流。有一些想法可以制作一种类似流的额外数据类型,该数据类型将具有自己的语法,但是如果有的话,这些想法是高度实验性的,我将不赘述。 无论如何,您的回调仅等待流结束,这非常适合兑现承诺。您只需要包装流: 现

  • 问题内容: 我试图摆脱使用Mongoose Promise与Node.js的async / await功能的束缚。调用我的函数时,我想保存该函数查询的员工列表。同时,内部的语句返回期望的查询,在内部的returns返回,表明我没有正确返回promise。 我对承诺完全陌生,以至于我没有正确理解范例……非常感谢您的帮助。 问题答案: 您需要这样做,否则您正在等待返回的函数。 当前,您正在等待非承诺,