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

React滚动加载电影:page状态更新但API请求仍用page=1的问题

问题分析

  1. 核心问题:闭包捕获旧状态
    fetchMovies函数在组件首次渲染时被定义,此时它的闭包环境捕获了page的初始值1。后续虽然通过setPage更新了状态,但fetchMovies函数本身没有重新创建——它一直沿用首次定义时捕获的page=1,所以每次API请求的参数始终是page=1。

  2. 状态更新方式的正确性
    你使用setPage((prevPage) => prevPage + 1)这种函数式更新的写法是完全正确的。这种写法基于最新的前一次状态计算新值,避免了直接依赖page变量可能导致的状态不同步问题,是处理依赖前状态的标准写法。

解决方案

要解决这个问题,需要让fetchMovies每次都能获取到最新的page值,同时处理滚动事件的闭包问题,具体方案如下:

方案一:用useCallback包裹函数,更新依赖

通过useCallback让fetchMovies在page变化时重新创建,确保捕获最新的page值,同时修复滚动事件的闭包问题:

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

const fetchMovies = useCallback(async () => {
  const options = {
    method: "GET",
    headers: {
      accept: "application/json",
      Authorization: "Bearer " + bearerToken,
    },
  };
  setLoading(true);
  try {
    const res = await fetch(
      `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${page}`,
      options
    );
    const data = await res.json();
    setPage(prev => prev + 1);
    setMovies(prev => [...prev, ...data.results]);
  } catch (error) {
    console.error(error);
  }
  setLoading(false);
}, [page, bearerToken]);

const handleScroll = useCallback(() => {
  const { scrollTop, clientHeight, scrollHeight } = document.documentElement;
  if (scrollTop + clientHeight >= scrollHeight - 5 && !loading) {
    fetchMovies();
  }
}, [fetchMovies, loading]);

useEffect(() => {
  window.addEventListener("scroll", handleScroll);
  return () => {
    window.removeEventListener("scroll", handleScroll);
  };
}, [handleScroll]);

方案二:请求前缓存当前页码

如果不想频繁创建函数,也可以在fetchMovies内部先缓存当前的page值,确保请求用的是调用函数时的最新页码:

const fetchMovies = async () => {
  const currentPage = page; // 缓存当前page值
  const options = { /* ... */ };
  setLoading(true);
  try {
    const res = await fetch(
      `https://api.themoviedb.org/3/movie/popular?language=en-US&page=${currentPage}`,
      options
    );
    const data = await res.json();
    setPage(prev => prev + 1);
    setMovies(prev => [...prev, ...data.results]);
  } catch (error) {
    console.error(error);
  }
  setLoading(false);
};

这种方式不需要额外的Hook,适合简单场景,即使page在请求过程中更新,也不会影响当前请求的页码。


内容的提问来源于stack exchange,提问作者sameer sheikh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:27:47