【问题标题】:Waiting for useState hook increment counter using Promises使用 Promises 等待 useState 钩子递增计数器
【发布时间】:2021-12-04 16:02:36
【问题描述】:

我有一个计数器需要在渲染我的 DOM 之前更新。

const [count, setCount] = useState(1);

每当用户滚动时,我都需要更新它,并调用函数 fetchMoreData。

所以我将它添加到 Promise 中并等到更新相同

const fetchMoreData = async () => {
    await new Promise((resolve, reject) => {
      setCount(count+1);
      resolve();
    });
    updateNews();
};

但这似乎不起作用,并且计数不会立即增加。

我该如何解决?

编辑:在聊天中,A.mola 帮我解决了问题,所以他给我的答案是根据我的代码,我在这里发布相同的内容。

import React, { useEffect, useState } from "react";
import NewsItem from "./NewsItem";
import Spinner from "./Spinner";
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";

const News = (props) => {
  const [articles, setArticles] = useState([]);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);
  const [totalResults, setTotalResults] = useState(0);

  const capitalizeFirstLetter = (string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
  };

  const updateNews = async () => {
    props.setProgress(10);
    let goToPage = page;
    const url = `newsapi.org/v2/…${props.country}&category=${props.category}&apiKey=${props.apiKey}&page=${goToPage}&pageSize=${props.pageSize}`;
    props.setProgress(30);
    let data = await fetch(url);
    props.setProgress(50);
    let parsedData = await data.json();
    props.setProgress(70);
    if (parsedData) {
      setArticles(articles.concat(parsedData.articles));
      setLoading(false);
      setPage(page);
      setTotalResults(parsedData.totalResults);
    }
    props.setProgress(100);
  };

  useEffect(() => {
    updateNews();
    // eslint-disable-next-line
  }, []);

  const fetchMoreData = async () => {
    setPage((page) => {
      console.log(page);
      return page + 1;
    });
    console.log(page);
    updateNews();
  };
  return (
    <>
      <h3 className="text-center" style={{ marginTop: "4%" }}>
        NewsMonkey - Top {`${capitalizeFirstLetter(props.category)}`} Headlines
      </h3>
      {loading && <Spinner />}
      <InfiniteScroll
        dataLength={articles.length}
        next={fetchMoreData}
        hasMore={articles.length < totalResults}
        loader={<Spinner />}
      >
        <div className="container">
          <div className="row">
            {articles.map((element) => {
              return (
                <div className="col-md-4" key={element.url}>
                  <NewsItem
                    title={
                      element && element.title ? element.title.slice(0, 45) : ""
                    }
                    description={
                      element && element.description
                        ? element.description.slice(0, 50)
                        : ""
                    }
                    imageUrl={element.urlToImage}
                    newsUrl={element.url}
                    author={element.author}
                    date={element.publishedAt}
                    source={element.source.name}
                  />
                </div>
              );
            })}
          </div>
        </div>
      </InfiniteScroll>
    </>
  );
};

【问题讨论】:

  • setState 函数异步更新状态。使用功能更新,因为您想使用过去的值。 reactjs.org/docs/hooks-reference.html#functional-updates
  • 但除了承诺之外,难道不应该等待吗?
  • 它不返回 Promise 所以 await 对它没有影响。只需在没有Promise 的情况下使用setCount 上的功能更新
  • const fetchMoreData = async () =&gt; { setCount(count =&gt; count+ 1); updateNews(); }; 试过了,但是不行
  • 尝试登录控制台,每次都给1

标签: javascript reactjs async-await react-hooks use-state


【解决方案1】:

感谢 a.mola 的全面回答,我正在更新您在聊天中给我的回答。

我们正在使用useEffect 钩子来使用数组依赖来渲染我们的组件。

import React, { useEffect, useState } from "react";
import NewsItem from "./NewsItem";
import Spinner from "./Spinner";
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";

const News = ({ country, category, apiKey, pageSize, setProgress }) => {
    const [articles, setArticles] = useState([]);
    const [loading, setLoading] = useState(true);
    const [page, setPage] = useState(1);
    const [totalResults, setTotalResults] = useState(0);

    const capitalizeFirstLetter = (string) => {
        return string.charAt(0).toUpperCase() + string.slice(1);
    };

    useEffect(() => {
        const updateNews = async () => {
            setProgress(10);
            let goToPage = page;
            const url = `newsapi.org/v2/…${country}&category=${category}&apiKey=${apiKey}&page=${goToPage}&pageSize=${pageSize}`;
            setProgress(30);
            let data = await fetch(url);
            setProgress(50);
            let parsedData = await data.json();
            setProgress(70);
            if (parsedData) {
                setArticles(articles.concat(parsedData.articles));
                setLoading(false);
                setTotalResults(parsedData.totalResults);
            }
            setProgress(100);
        };

        updateNews();
    }, [page, articles, pageSize, setProgress, apiKey, category, country]);

    const fetchMoreData = () => setPage(page + 1);

    return (
        <>
            <h3 className="text-center" style={{ marginTop: "4%" }}>
                NewsMonkey - Top {`${capitalizeFirstLetter(category)}`} Headlines
            </h3>
            {loading && <Spinner />}
            <InfiniteScroll dataLength={articles.length} next={fetchMoreData} hasMore={articles.length < totalResults} loader={<Spinner />}>
                <div className="container">
                    <div className="row">
                        {articles.map((element) => {
                            return (
                                <div className="col-md-4" key={element.url}>
                                    <NewsItem title={element && element.title ? element.title.slice(0, 45) : ""} description={element && element.description ? element.description.slice(0, 50) : ""} imageUrl={element.urlToImage} newsUrl={element.url} author={element.author} date={element.publishedAt} source={element.source.name} />
                                </div>
                            );
                        })}
                    </div>
                </div>
            </InfiniteScroll>
        </>
    );
};

这里是codeandbox链接:https://codesandbox.io/s/proud-shape-58yig?file=/Infinite.tsx:0-2597

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 2021-04-04
    • 2019-10-20
    • 2020-12-16
    • 2020-08-15
    • 2019-04-23
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多