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

React Native中useState分页状态更新异常问题求助

解决React Native中WordPress API分页的状态更新问题

我来帮你排查下代码里的问题,主要是React状态更新的异步特性和数据请求时机没处理对,这是React开发里很常见的小坑。咱们一步一步来修复:

问题根源分析

  1. 状态更新的异步性:当你在nextHandler或previousHandler里调用setPage(newPage)后,立即执行fetchData(),这时候page状态还没完成更新——React的状态更新是异步批量处理的,所以fetchData里用的还是旧的page值,导致首次点击时请求的还是第1页的数据,看起来状态没变化。
  2. 数据请求逻辑分散:你把数据请求同时放在了组件挂载的useEffect和点击 handler里,没有利用React的状态依赖机制来自动触发请求,导致状态更新和数据不同步,进而引发按钮显示异常。

修复后的完整代码

import React, { useState, useEffect } from "react";
import { View, FlatList, TouchableOpacity } from "react-native";
import { Colors } from "../constant/colors";
import globalStyles from "../constant/globalStyle";
import axios from "axios";
import PostCard from "../components/PostCard";
import CustomButton from "../components/Button";

const Updates = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [loaded, setLoaded] = useState(false);

  // 监听page状态变化,自动触发数据请求
  useEffect(() => {
    fetchData();
  }, [page]); // 依赖数组添加page,page更新时自动执行

  const fetchData = async () => {
    setLoaded(false); // 开始请求前先标记为未加载
    try {
      const response = await axios.get(
        `https://bachrasouthpanchayat.in/wp-json/wp/v2/posts?embed=true&page=${page}`
      );
      setData(response.data);
    } catch (error) {
      // 可以在这里添加错误处理,比如提示用户加载失败
      console.error("Failed to fetch posts:", error);
    } finally {
      setLoaded(true); // 请求完成(无论成功失败)都标记为已加载
    }
  };

  const previousHandler = () => {
    // 用函数式更新确保拿到最新的page状态
    setPage(prevPage => prevPage - 1);
  };

  const nextHandler = () => {
    // 函数式更新避免闭包捕获旧状态
    setPage(prevPage => prevPage + 1);
  };

  return (
    <View
      style={{
        ...globalStyles.container,
        backgroundColor: Colors.BACKGROUND_SCREEN,
      }}
    >
      {loaded ? (
        <>
          <FlatList
            style={{ flex: 1, margin: 10 }}
            data={data}
            keyExtractor={(item) => item.id.toString()} // 确保key是字符串,避免警告
            renderItem={({ item }) => {
              return (
                <TouchableOpacity activeOpacity={0.7}>
                  <PostCard
                    title={item.title.rendered}
                    imageUrl={item.jetpack_featured_media_url}
                  />
                </TouchableOpacity>
              );
            }}
          />
          <View
            style={{
              flexDirection: "row",
              alignItems: "center",
              justifyContent: "center",
              marginBottom: 10, // 给按钮加个底部边距,避免贴屏
            }}
          >
            {page === 1 ? ( // 用严格相等===更规范
              <TouchableOpacity
                activeOpacity={0.7}
                style={{ width: "100%" }}
                onPress={nextHandler}
              >
                <CustomButton>Next</CustomButton>
              </TouchableOpacity>
            ) : (
              <>
                <TouchableOpacity
                  activeOpacity={0.7}
                  style={{ marginRight: 2, width: "50%" }}
                  onPress={previousHandler}
                >
                  <CustomButton>Previous</CustomButton>
                </TouchableOpacity>
                <TouchableOpacity
                  activeOpacity={0.7}
                  style={{ width: "50%" }}
                  onPress={nextHandler}
                >
                  <CustomButton>Next</CustomButton>
                </TouchableOpacity>
              </>
            )}
          </View>
        </>
      ) : (
        // 可以在这里添加加载状态组件,比如ActivityIndicator
        <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
          {/* <ActivityIndicator size="large" color={Colors.PRIMARY} /> */}
        </View>
      )}
    </View>
  );
};

export default Updates;

关键修改点说明

  1. 让useEffect监听page状态:把page加入useEffect的依赖数组,这样每当page更新时,自动调用fetchData请求对应页码的数据,彻底避免了手动调用时的异步状态问题。
  2. 使用函数式更新setPage:setPage(prevPage => prevPage ±1)这种写法可以确保拿到当前最新的page值,避免闭包中捕获旧状态的问题,尤其在频繁点击按钮时更可靠。
  3. 统一加载状态逻辑:把setLoaded(false)移到fetchData开头,用try/catch/finally确保无论请求成功还是失败,最终都会标记为已加载,避免页面一直处于空白状态。
  4. 优化细节:给keyExtractor的结果转成字符串(避免React警告),给按钮容器加了底部边距,还预留了加载状态的位置,提升用户体验。

现在你再测试一下:点击Next按钮,page会正确递增到2,useEffect自动触发请求第2页的数据,加载完成后会显示Previous和Next两个按钮;点击Previous,page回到1,按钮会自动切换成只显示Next,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Shoubhik Raj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 06:42:41