我有点像:

const [loading, setLoading] = useState(false);

...

setLoading(true);
doSomething(); // <--- when here, loading is still false. 

设置状态仍然是异步的,那么等待这个setLoading()调用完成的最佳方式是什么呢?

setLoading()似乎不像以前的setState()那样接受回调.

一个例子

基于类的

getNextPage = () => {
    // This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
    goToTop();

    if (this.state.pagesSeen.includes(this.state.page + 1)) {
      return this.setState({
        page: this.state.page + 1,
      });
    }

    if (this.state.prefetchedOrders) {
      const allOrders = this.state.orders.concat(this.state.prefetchedOrders);
      return this.setState({
        orders: allOrders,
        page: this.state.page + 1,
        pagesSeen: [...this.state.pagesSeen, this.state.page + 1],
        prefetchedOrders: null,
      });
    }

    this.setState(
      {
        isLoading: true,
      },
      () => {
        getOrders({
          page: this.state.page + 1,
          query: this.state.query,
          held: this.state.holdMode,
          statuses: filterMap[this.state.filterBy],
        })
          .then((o) => {
            const { orders } = o.data;
            const allOrders = this.state.orders.concat(orders);
            this.setState({
              orders: allOrders,
              isLoading: false,
              page: this.state.page + 1,
              pagesSeen: [...this.state.pagesSeen, this.state.page + 1],
              // Just in case we're in the middle of a prefetch.
              prefetchedOrders: null,
            });
          })
          .catch(e => console.error(e.message));
      },
    );
  };

转换为基于函数的

  const getNextPage = () => {
    // This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
    goToTop();

    if (pagesSeen.includes(page + 1)) {
      return setPage(page + 1);
    }

    if (prefetchedOrders) {
      const allOrders = orders.concat(prefetchedOrders);
      setOrders(allOrders);
      setPage(page + 1);
      setPagesSeen([...pagesSeen, page + 1]);
      setPrefetchedOrders(null);
      return;
    }

    setIsLoading(true);

    getOrders({
      page: page + 1,
      query: localQuery,
      held: localHoldMode,
      statuses: filterMap[filterBy],
    })
      .then((o) => {
        const { orders: fetchedOrders } = o.data;
        const allOrders = orders.concat(fetchedOrders);

        setOrders(allOrders);
        setPage(page + 1);
        setPagesSeen([...pagesSeen, page + 1]);
        setPrefetchedOrders(null);
        setIsLoading(false);
      })
      .catch(e => console.error(e.message));
  };

在上面,我们希望按顺序运行每个setwhater调用.这是否意味着我们需要设置许多不同的useEffect挂钩来复制这种行为?

推荐答案

useState setter在状态更新完成后不会像React类组件中的setState那样提供回调.为了复制相同的行为,您可以在React类组件中使用类似的模式,比如componentDidUpdate lifecycle方法,useEffect使用钩子

useEffect hooks将第二个参数作为一个值数组,在渲染周期完成后,这些值需要监控更改.

const [loading, setLoading] = useState(false);

...

useEffect(() => {
    doSomething(); // This is be executed when `loading` state changes
}, [loading])
setLoading(true);

EDIT

setState不同,useState hook的更新程序没有回调,但您可以始终使用useEffect来复制上述行为.但是,您需要确定加载更改

代码的函数方法如下所示

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

const prevLoading = usePrevious(isLoading);

useEffect(() => {
   if (!prevLoading && isLoading) {
       getOrders({
          page: page + 1,
          query: localQuery,
          held: localHoldMode,
          statuses: filterMap[filterBy],
      })
      .then((o) => {
        const { orders: fetchedOrders } = o.data;
        const allOrders = orders.concat(fetchedOrders);

        setOrders(allOrders);
        setPage(page + 1);
        setPagesSeen([...pagesSeen, page + 1]);
        setPrefetchedOrders(null);
        setIsLoading(false);
      })
      .catch(e => console.error(e.message));
   }
}, [isLoading, preFetchedOrders, orders, page, pagesSeen]);

const getNextPage = () => {
    // This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
    goToTop();

    if (pagesSeen.includes(page + 1)) {
      return setPage(page + 1);
    }

    if (prefetchedOrders) {
      const allOrders = orders.concat(prefetchedOrders);
      setOrders(allOrders);
      setPage(page + 1);
      setPagesSeen([...pagesSeen, page + 1]);
      setPrefetchedOrders(null);
      return;
    }

    setIsLoading(true);
  };

Reactjs相关问答推荐

从`redux—thunk`导入thunk `在stackblitz中不起作用

如何在react组件中使用formik进行验证

更改购物车中的产品数量后,PayPal Reaction/Next JS按钮未更新

Reaction-Query&-使用Mutation触发成功,而应该触发错误

如何在NextJS中仅在刷新页面和页面淡出页面过渡时添加全屏加载器

无法在REACTION TANSTACK查询中传递参数

透明MOV文件未出现在我的React网页中

useRef()的钩子调用无效

在react上隐藏源映射

通过createRoot创建的React元素无法调用Provider值

拖放 - 将排序保存到数组字段

为什么在 React 的 useEffect 中使用 onAuthStateChanged ?

修改React数据表扩展组件

如何管理可重用无线电输入的 React 状态?

从 redux 调用UPDATE_DATA操作时状态变得未定义

React中useAuthenticator的authState在成功登录后仍保持未认证状态 - 需要强制刷新

无法访问 usefocusEffect 中 const 的更新状态

部署到github pages时请求路径错误

从服务器获取数据时未定义,错误非法调用

react / firebase 基地.如何在我的项目中保存更新的数据?