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
相关产品推荐
相关产品推荐

