You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么React Hooks组件中fetch请求到的数据没有正常显示?

问题原因

  • setOfferings是React提供的异步更新方法,调用后不会立刻修改当前作用域下的offerings变量,而是会把更新任务推入队列,等当前渲染周期结束后才会触发重渲染更新变量值,所以你在setOfferings后立刻打印拿到的永远是当前渲染周期的旧值(也就是初始的空数组)。
  • 直接给useEffect传入async函数是错误写法:useEffect期望返回值是可选的清理函数,而async函数默认返回Promise,会导致清理逻辑失效,甚至引发内存泄漏。

解决方法

1. 新增加载状态控制渲染逻辑

新增isLoading状态标记数据加载进度,加载完成前显示占位内容,加载完成后再渲染业务组件,避免提前展示无数据的提示。

2. 修正异步逻辑写法

把异步逻辑封装在useEffect内部的自执行函数中,避免直接给useEffect传async函数,同时添加请求错误捕获逻辑避免页面崩溃。

3. 调整状态打印逻辑

如果需要查看更新后的offerings值,可以单独用useEffect监听offerings变化后再打印,或者直接打印接口返回的原始数据。

修正后参考代码

import { useState, useEffect, useDispatch, useSelector } from 'react';
// 其他导入省略

const HomeNew = () => {
  const [offerings, setOfferings] = useState([]);
  // 新增加载状态
  const [isLoading, setIsLoading] = useState(true);
  // 可选:新增错误状态
  const [loadError, setLoadError] = useState(null);

  const loadData = async () => {
    try {
      setIsLoading(true);
      setLoadError(null);
      const res = await fetch(`http://52.207.83.69${CRUD_OFFERING}`);
      if (!res.ok) throw new Error('请求失败');
      const result = await res.json();
      setOfferings(result); 
      // 要查看接口返回的数据直接打印result即可
      console.log(result, '接口返回的offerings数据');
    } catch (err) {
      setLoadError(err.message);
      console.error('加载数据失败:', err);
    } finally {
      setIsLoading(false);
    }
  };

  useEffect(() => {
    navbarToggle();
    // 在内部调用异步函数,不要给useEffect直接传async
    (async () => {
      await loadData();
    })();
  }, []);

  // 监听offerings变化,打印更新后的值
  useEffect(() => {
    console.log(offerings, '更新后的offerings');
  }, [offerings]);

  const dispatch = useDispatch();
  const modalState = useSelector((state) => state.modal);
  const modalToggle = () => {
    dispatch({
      type: MODAL_TOGGLE,
      payload: !modalState.show,
    });
    ga.event("navbar_requestdemo_clicked");
  };
  const navbarOpenState = useSelector((state) => state.navbar);
  const navbarToggle = () => {
    if (!navbarOpenState.open) return;
    dispatch({
      type: NAVBAR_OPEN,
      payload: false,
    });
  };

  // 加载中状态展示
  if (isLoading) {
    return <div className="text-center py-5">数据加载中...</div>;
  }

  // 加载失败状态展示
  if (loadError) {
    return <div className="text-center py-5 text-danger">加载失败:{loadError}</div>;
  }

  return (
    <div
      className="d-flex justify-content-center align-items-center bg-color-white fc-px-15"
      onClick={navbarToggle}
    >
      <div className={homeStyles["padded-body"] + " col-11 p-0"}>
        <div className=" position-relative bg-color-white">
          <div className={homeStyles["img-holder"]}></div>
          <div className="col-12 column position-absolute top-0 d-flex justify-content-center">
            <div className="col-lg-6 col-12 fc-mt-2">
              <SearchBar />
            </div>
          </div>
          <div className="position-absolute top-50 translateY-middle">
            <div className="position-relative">
              <h1 className={`${homeStyles["hero-text"]} font-weight-bolder`}>
                Building
                <br />
                Meaningful
                <br />
                Engagement
              </h1>
              <button
                className="btn btn-primary-round mt-3 px-3 py-2"
                onClick={() => {
                  modalToggle();
                }}
              >
                Request access
              </button>
            </div>
          </div>
        </div>
        <div
          id={homeStyles["discover-section"]}
          className="d-flex justify-content-center align-items-center"
        >
          <div className="col-12 column">
            <h4 className="font-weight-bold">Discover</h4>
            <div
              id={homeStyles["offer-section"]}
              className="row justify-content-center align-items-center"
            >
              {!offerings?.length && 
                <h4 className="text-center">There are no active offerings.</h4>
              }
            </div>
            <OfferingCarousal
              offeringsList={offerings}
              name={"Offerings"}
            />
            <div id={homeStyles["consultancy-section"]} className="">
              <div className="row">
                <div
                  className="d-flex justify-content-center align-items-center col-lg-6 col-12 px-0 mt-3 mb-4"
                  id={homeStyles["consultancy-div"]}
                >
                  <div className="col-12 column p-5">
                    <h1 className="font-weight-bold">Add your consultancy</h1>
                    <h5 className="mt-4">
                      Reach more people and organizations
                    </h5>
                    <Link href="/consultancies">
                      <button className="btn btn-primary-round mt-4">
                        Learn more
                      </button>
                    </Link>
                  </div>
                </div>
                <div className="col-lg-6 col-12 px-0">
                  <img
                    src="/images/Rachael_glasses_home_page.jpg"
                    id={homeStyles["consultant-img"]}
                    className="mt-3"
                    alt="咨询顾问"
                  />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default HomeNew;

内容的提问来源于stack exchange,提问作者Billy Keef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 06:21:01