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

React项目中Axios的Promise then用法是否正确?如何控制渲染时机?

React Axios 请求与渲染控制问题解答

嘿,我来帮你拆解下这个问题~

首先先回答你最关心的:你的then用法本身语法上是正确的,但代码里有几个可以优化的点,而且你提到的“状态被设置两次”其实是个误解,咱们一步步说:

为什么会看到两次状态相关的渲染?

你实际遇到的是两次组件渲染,而不是两次设置状态:

  1. 组件挂载时,componentWillMount调用getUsers,此时axios请求还在进行中,组件会先以初始空数组的databaseUsers状态渲染一次;
  2. 当axios请求完成,then回调里执行setState,触发组件重新渲染,这时候databaseUsers才有真实数据。

这是React处理异步请求的正常流程,并不是then触发了两次状态设置哦。

代码里的小问题与优化点

  1. 弃用的生命周期:componentWillMount已经从React v16.3开始被标记为不安全的生命周期,推荐改用componentDidMount来发起数据请求——它在组件挂载后只执行一次,更可靠,也避免了服务器端渲染时的重复调用问题。
  2. 无用的变量赋值:你把axios.get()的结果赋值给users,但这个变量其实是一个Promise对象,不是获取到的用户数据,完全可以删掉这个赋值。

如何获得渲染控制权:等待数据返回再渲染?

想要让用户只看到加载完成后的内容,最常用的方案是添加加载状态(loading),或者在父组件提前获取数据再传递。下面给你两种具体实现:

方案1:组件内部管理加载状态(最常用)

给state新增isLoading字段,初始为true,请求完成后设为false,render时根据这个状态决定显示加载提示还是实际内容:

class Participants extends React.Component{
  constructor(props){
    super(props);
    this.state = { 
      databaseUsers: [],
      isLoading: true // 新增加载状态
    }
    this.getUsers = this.getUsers.bind(this);
  }

  // 用async/await改造,让异步代码更易读
  async getUsers(){ 
    try {
      const response = await axios.get('/users/get-users');
      this.setState({
        databaseUsers: response.data,
        isLoading: false // 请求完成,关闭加载状态
      });
    } catch (error) {
      console.error('获取用户数据失败:', error);
      this.setState({ isLoading: false }); // 出错也要关闭加载,避免卡死
    }
  }

  // 替换为componentDidMount
  componentDidMount(){ 
    this.getUsers();
  }

  render(){
    const { isLoading, databaseUsers } = this.state;
    
    // 加载中时显示提示
    if (isLoading) {
      return <div>加载用户数据中...</div>;
    }

    // 数据就绪后渲染实际内容
    console.log(databaseUsers);
    return (
      <div>
        {databaseUsers.map(user => (
          <div key={user.id}>{user.name}</div>
        ))}
      </div>
    );
  }
}

方案2:父组件提前获取数据(实现单次渲染)

如果希望Participants组件挂载时就有数据,完全不需要初始空渲染,可以把请求逻辑放到父组件里,等数据就绪后再渲染Participants:

// 父组件
class UserList extends React.Component {
  state = { 
    users: [],
    isLoading: true 
  };

  async componentDidMount() {
    try {
      const response = await axios.get('/users/get-users');
      this.setState({ users: response.data, isLoading: false });
    } catch (error) {
      console.error('获取数据失败:', error);
      this.setState({ isLoading: false });
    }
  }

  render() {
    if (this.state.isLoading) {
      return <div>加载中...</div>;
    }
    // 数据就绪后才渲染Participants组件
    return <Participants databaseUsers={this.state.users} />;
  }
}

// Participants组件(简化)
class Participants extends React.Component{
  render(){
    console.log(this.props.databaseUsers);
    return (
      <div>
        {this.props.databaseUsers.map(user => (
          <div key={user.id}>{user.name}</div>
        ))}
      </div>
    );
  }
}

这样Participants组件只会在数据准备好后被挂载,自然只会渲染一次。

总结

  • 你的then用法没问题,但用async/await能让异步逻辑更清晰;
  • 两次渲染是React的正常流程,通过loading状态可以让用户无感知;
  • 想要彻底避免初始空渲染,就把请求逻辑上移到父组件,提前准备好数据再传递。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:44:33