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

React中useState变量nextToken在fetch请求成功后未更新

解决React中useState异步更新导致分页token无法拼接的问题

你的代码里有两个核心问题,导致nextToken始终没法正确拼接到请求URL中:

  • React状态更新是异步的:调用setNextToken(json.nextPageToken)后,nextToken不会立刻变成新值,所以你紧接着console.log(nextToken)打印的还是初始的null——这是React的正常机制,不是代码bug。
  • 缺少触发下一页请求的逻辑:当前代码只在组件挂载时调用一次getVideos,哪怕nextToken被更新成了有效值,也不会自动发起下一页请求;就算你手动触发加载,也可能因为没拿到最新状态值导致URL拼接失败。

修复后的完整代码

import { useCallback, useEffect, useState } from "react";

// 替换成你的实际接口地址
const API_URL = "https://example.com/api/videos";

const VideoList = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [videos, setVideos] = useState([]);
  const [nextToken, setNextToken] = useState(null);

  // 用useCallback包裹,确保每次状态更新时函数能拿到最新的nextToken
  const getVideos = useCallback(async () => {
    if (isLoading) return; // 防止重复触发请求
    setIsLoading(true);
    
    try {
      // 这里会使用最新的nextToken拼接URL
      const url = nextToken ? `${API_URL}&token=${nextToken}` : API_URL;
      console.log("Fetching data from:", url);

      const data = await fetch(url);
      if (!data.ok) throw new Error("请求数据失败");

      const json = await data.json();
      setNextToken(json.nextPageToken);
      // 合并新数据到现有列表
      setVideos(prev => [...prev, ...json.items]);
    } catch (error) {
      console.error("加载视频出错:", error);
    } finally {
      setIsLoading(false);
    }
  }, [nextToken, isLoading]);

  // 组件挂载时加载第一页
  useEffect(() => {
    getVideos();
  }, [getVideos]);

  // 渲染视频列表和加载更多按钮
  return (
    <div>
      <div className="video-list">
        {videos.map(video => (
          <div key={video.id} className="video-item">
            {video.title}
          </div>
        ))}
      </div>
      {/* 有下一页token且未加载时显示加载按钮 */}
      {nextToken && !isLoading && (
        <button onClick={getVideos}>加载更多</button>
      )}
      {isLoading && <p>加载中...</p>}
    </div>
  );
};

export default VideoList;

关键修复说明

  1. 用useCallback包裹请求函数:把nextToken和isLoading加入依赖数组,确保每次这两个状态更新时,getVideos函数都会拿到最新的值,避免闭包导致的旧状态问题。
  2. 添加重复请求拦截:通过isLoading状态判断,防止用户多次点击加载按钮导致重复请求。
  3. 正确监听状态变化:如果要查看更新后的nextToken,不要在setNextToken后立刻打印,而是添加一个单独的useEffect监听:
useEffect(() => {
  console.log("当前分页token:", nextToken);
}, [nextToken]);

内容的提问来源于stack exchange,提问作者Vishal Tanna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:32:31