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

React类组件:autoPagination无法在userSaves初始更新时触发的解决方案求助

解决autoPagination在userSaves初始化完成前执行的问题

你的核心问题在于componentDidMount中调用storeInitialData后,userSaves的Redux状态更新是异步的,导致你直接调用autoPagination时拿不到初始化后的100条数据,而setTimeout只是靠硬等待规避问题,显然不健壮。下面给你几个更可靠的方案:

问题根源拆解

  1. storeInitialData是异步更新Redux状态的,所以在componentDidMount执行完后,this.props.userSaves还是初始的空数组
  2. 你需要在userSaves真正被填充数据后,再触发分页逻辑

方案一:利用componentDidUpdate生命周期(推荐)

类组件的componentDidUpdate会在props或state变化时触发,我们可以在这里监听userSaves的变化,当它从空数组变为有数据时启动分页,同时加标志位避免重复执行:

步骤1:添加组件状态存储token和分页状态

state = {
  accessToken: '',
  isPaginationRunning: false // 防止重复触发分页逻辑
}

步骤2:修改componentDidMount,把token存到组件state

componentDidMount() {
  const params = new URLSearchParams(this.props.location.hash);
  const token = params.get('#access_token');
  this.setState({ accessToken: token });
  this.props.storeInitialData(token);
}

步骤3:实现componentDidUpdate监听userSaves变化

componentDidUpdate(prevProps) {
  // 当userSaves从空变为有数据,且分页未在运行时,启动分页
  if (prevProps.userSaves.length === 0 && this.props.userSaves.length > 0 && !this.state.isPaginationRunning) {
    this.setState({ isPaginationRunning: true }, () => {
      this.autoPagination(this.state.accessToken);
    });
  }
}

步骤4:优化autoPagination的循环逻辑

原有的while循环可能因为props更新不及时导致逻辑异常,改成递归调用更稳妥:

autoPagination = async token => { 
  const { userSaves } = this.props;
  // 无数据时直接终止
  if (userSaves.length === 0) {
    this.setState({ isPaginationRunning: false });
    return;
  }

  const lastPage = userSaves[userSaves.length-1].data.name; 
  try {
    const userSavesObject = await axios.get(`https://oauth.reddit.com/user/${this.props.username}/saved/.json?limit=100&after=${lastPage}`, { 
      headers: { 'Authorization': `bearer ${token}` } 
    }); 
    const currentPageSaves = userSavesObject.data.data.children;

    // 没有更多数据时停止分页
    if (currentPageSaves.length === 0) {
      this.setState({ isPaginationRunning: false });
      return;
    }

    this.props.storeUserHistory(currentPageSaves); 
    this.props.appendUserHistory(currentPageSaves); 
    
    // 递归调用继续分页
    this.autoPagination(token);
  } catch (err) {
    console.error('分页请求出错:', err);
    this.setState({ isPaginationRunning: false });
  }
} 

方案二:让storeInitialData返回Promise(可选)

如果你的storeInitialData是异步action(内部包含API请求),可以让它返回Promise,这样在componentDidMount中就能用await等待初始化完成后再调用分页:

// 假设修改后的storeInitialData action返回Promise
componentDidMount = async () => {
  const params = new URLSearchParams(this.props.location.hash);
  const token = params.get('#access_token');
  // 等待初始数据加载完成
  await this.props.storeInitialData(token);
  // 此时userSaves已经有数据了
  this.autoPagination(token);
}

这个方案更简洁,但前提是你能修改storeInitialData的实现,让它返回异步操作的Promise。


修改后的完整组件代码

import axios from 'axios'; 
import React from 'react'; 
import { connect } from 'react-redux'; 
import { storeUserHistory, appendUserHistory, storeInitialData } from '../actions/index.js' 

class ListSaved extends React.Component { 
  state = {
    accessToken: '',
    isPaginationRunning: false
  }

  componentDidMount() { 
    const params = new URLSearchParams(this.props.location.hash); 
    const token = params.get('#access_token');
    this.setState({ accessToken: token });
    this.props.storeInitialData(token); 
  } 

  componentDidUpdate(prevProps) {
    if (prevProps.userSaves.length === 0 && this.props.userSaves.length > 0 && !this.state.isPaginationRunning) {
      this.setState({ isPaginationRunning: true }, () => {
        this.autoPagination(this.state.accessToken);
      });
    }
  }

  autoPagination = async token => { 
    const { userSaves } = this.props;
    if (userSaves.length === 0) {
      this.setState({ isPaginationRunning: false });
      return;
    }

    const lastPage = userSaves[userSaves.length-1].data.name; 
    try {
      const userSavesObject = await axios.get(`https://oauth.reddit.com/user/${this.props.username}/saved/.json?limit=100&after=${lastPage}`, { 
        headers: { 'Authorization': `bearer ${token}` } 
      }); 
      const currentPageSaves = userSavesObject.data.data.children;

      if (currentPageSaves.length === 0) {
        this.setState({ isPaginationRunning: false });
        return;
      }

      this.props.storeUserHistory(currentPageSaves); 
      this.props.appendUserHistory(currentPageSaves); 
      
      this.autoPagination(token);
    } catch (err) {
      console.error('分页请求出错:', err);
      this.setState({ isPaginationRunning: false });
    }
  } 

  renderPostTitles = () => { 
    return this.props.totalSaves.map((saved) => { 
      return ( 
        <div key={saved.data.id}> 
          <div>{saved.data.title}</div> 
        </div> 
      ) 
    }) 
  } 

  render () { 
    return <div>{this.renderPostTitles()}</div> 
  } 
} 

const mapStateToProps = state => { 
  console.log(state) 
  return { 
    username: state.username, 
    userSaves: state.userHistory, 
    totalSaves: state.totalUserHistory 
  } 
} 

export default connect(mapStateToProps, { storeUserHistory, appendUserHistory, storeInitialData })(ListSaved);

内容的提问来源于stack exchange,提问作者Robert C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:42:31