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

Apollo(react-apollo):查询未变更时如何强制重新查询

我完全懂你的痛点——Apollo的缓存策略就是这样:只要查询语句和变量完全一致,它就会复用缓存结果,哪怕你调用forceUpdate也没用。这里有两个实用的解决办法,帮你实现强制重新查询的需求:


方法一:使用refetch函数(推荐)

Apollo的Query组件在render prop中会返回一个refetch方法,这个方法可以直接强制重新执行当前查询,完全忽略缓存和变量是否变化的限制。我们只需要把这个方法传递给父组件的按钮调用即可。

首先修改你的RandomName组件,把refetch暴露给父组件:

class RandomName extends React.Component {
  render() {
    const query = gql`
      query name($gender: String, $top: Int) {
        name(gender: $gender, top: $top) {
          firstName
          gender
          surname
        }
      }
    `;
    return (
      <Query
        query={query}
        variables={{ gender: this.props.gender, top: this.props.top }}
        fetchPolicy="network-only"
      >
        {({ loading, error, data, refetch }) => {
          // 把refetch方法传递给父组件
          this.props.onRefetchReady(refetch);
          
          if (loading) return <p>Loading...</p>;
          if (error) return <p>Error</p>;
          // 注意:原代码里漏了data.,这里要修正
          return <p>{data.name.firstName} {data.name.surname}</p>;
        }}
      </Query>
    );
  }
}

然后在父组件中保存这个方法,点击按钮时直接调用:

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.refetchName = null;
  }

  onClick() {
    if (this.refetchName) {
      // 直接调用refetch强制重新查询
      this.refetchName();
    }
  }

  render() {
    return (
      <div>
        <Button onClick={() => this.onClick()}>Get Name</Button>
        <RandomName
          gender={this.state.sendGender}
          top={this.state.sendTop}
          onRefetchReady={(refetch) => { this.refetchName = refetch; }}
        />
      </div>
    );
  }
}

方法二:添加“无效化”变量

如果不想用refetch,可以给查询添加一个额外的“无效化”变量(比如计数器或随机数)。每次点击按钮时更新这个变量,让Apollo认为查询参数发生了变化,从而重新发起请求。

修改RandomName组件,新增一个refreshKey变量(后端不需要处理这个变量,它只是用来触发查询):

class RandomName extends React.Component {
  render() {
    const query = gql`
      // 新增refreshKey变量,后端无需处理
      query name($gender: String, $top: Int, $refreshKey: Int) {
        name(gender: $gender, top: $top) {
          firstName
          gender
          surname
        }
      }
    `;
    return (
      <Query
        query={query}
        variables={{ 
          gender: this.props.gender, 
          top: this.props.top,
          refreshKey: this.props.refreshKey // 传入无效化变量
        }}
        fetchPolicy="network-only"
      >
        {({ loading, error, data }) => {
          if (loading) return <p>Loading...</p>;
          if (error) return <p>Error</p>;
          return <p>{data.name.firstName} {data.name.surname}</p>;
        }}
      </Query>
    );
  }
}

父组件中维护这个refreshKey状态,点击按钮时递增:

class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sendGender: 'male',
      sendTop: 10,
      refreshKey: 0 // 新增状态
    };
  }

  onClick() {
    this.setState(prevState => ({
      refreshKey: prevState.refreshKey + 1 // 每次点击更新变量
    }));
  }

  render() {
    return (
      <div>
        <Button onClick={() => this.onClick()}>Get Name</Button>
        <RandomName
          gender={this.state.sendGender}
          top={this.state.sendTop}
          refreshKey={this.state.refreshKey}
        />
      </div>
    );
  }
}

另外提醒下:你原代码里有个小bug,return <p>{name.firstName} {name.surname}</p>应该改成data.name.firstName,因为查询结果是存在data对象里的,不然会报变量未定义的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:07:12