React Native中如何从另一组件触发GraphQL查询并刷新组件A
解决React Native中GraphQL组件A点击按钮后不重新渲染的问题
我来帮你分析下这个问题,结合我在React Native + Apollo GraphQL开发中的经验,给你几个可行的解决方案:
1. 确保refetchQueries完全匹配组件A的查询配置
你当前用了refetchQueries但组件A没触发重新渲染,首先要检查这个配置是否和组件A中使用的查询完全一致:
- 确认
FETCH_SEARCH就是组件A里执行的那个查询,包括查询名称、变量定义(比如productcategory和search的类型、名称有没有拼写错误) - 组件A的查询代码应该和你
refetchQueries里的结构完全对应,比如:const FETCH_SEARCH = gql` query FetchSearch($productcategory: String!, $search: String!) { products(category: $productcategory, searchText: $search) { id name // 其他字段 } } `; - 如果变量名或查询名称不匹配,Apollo找不到对应的查询,自然不会触发重新请求。
2. 让组件A订阅Link State的筛选变量变化
既然你把筛选条件存到了GraphQL Link State,最可靠的方式是让组件A直接从Link State获取查询变量,这样当Link State更新时,组件A的查询会自动触发重新执行:
用HOC的方式(Class组件)
import { withApollo } from 'react-apollo'; import { GET_FILTERS } from './your-queries'; // 获取Link State筛选条件的查询 class ComponentA extends React.Component { render() { // 从Link State读取筛选变量 const { productcategory, search } = this.props.client.readQuery({ query: GET_FILTERS }); const { loading, data } = this.props.data; if (loading) return <ActivityIndicator />; return ( // 渲染你的数据列表 ); } } // 用withApollo包装组件,拿到client实例 export default withApollo(graphql(FETCH_SEARCH, { options: (props) => { const filters = props.client.readQuery({ query: GET_FILTERS }); return { variables: { productcategory: filters.productcategory || '', search: filters.search || '' } }; } })(ComponentA));
用Hooks的方式(Function组件)
import { useQuery, useApolloClient } from '@apollo/client'; import { FETCH_SEARCH, GET_FILTERS } from './your-queries'; const ComponentA = () => { const client = useApolloClient(); // 订阅Link State的筛选条件变化 const { data: filters } = useQuery(GET_FILTERS); // 每次filters变化时,自动重新执行FETCH_SEARCH const { loading, data } = useQuery(FETCH_SEARCH, { variables: { productcategory: filters?.productcategory || '', search: filters?.search || '' } }); if (loading) return <ActivityIndicator />; return ( // 渲染数据列表 ); };
这种方式下,当组件B更新Link State后,组件A的useQuery会自动检测到变量变化,触发重新查询并渲染新数据。
3. 手动触发组件A的查询刷新
如果refetchQueries不生效,可以在mutate完成后手动调用查询的refetch方法:
方式一:在mutate的回调中手动refetch
// 组件B的点击事件处理 handleButtonClick = (Category) => { this.props.mutate({ variables: { Category } }) .then(() => { // 先更新Link State this.props.client.writeData({ data: { productcategory: Category, search: '' } }); // 手动触发组件A的查询刷新 this.props.client.refetchQueries({ include: [FETCH_SEARCH], variables: { productcategory: Category, search: '' } }); }) .catch(err => console.error('Mutate failed:', err)); };
方式二:传递refetch方法给组件B
如果组件A和B是父子组件,可以把组件A查询的refetch方法传递给B,点击时直接调用:
// 组件A中 const ComponentA = () => { const { loading, data, refetch } = useQuery(FETCH_SEARCH, { variables: { /* 初始变量 */ } }); return <ComponentB onFilterClick={(category) => refetch({ productcategory: category, search: '' })} />; }; // 组件B中 const ComponentB = ({ onFilterClick }) => { const handleClick = (Category) => { mutate({ variables: { Category } }) .then(() => { // 更新Link State client.writeData({ data: { productcategory: Category } }); // 调用组件A的refetch方法 onFilterClick(Category); }); }; return <Button onPress={() => handleClick('electronics')} title="筛选电子类" />; };
4. 调整Apollo Client的缓存策略
有时候Apollo会因为缓存命中而不重新请求数据,可以在组件A的查询中设置fetchPolicy强制从网络获取:
const { loading, data } = useQuery(FETCH_SEARCH, { variables: { /* 变量 */ }, fetchPolicy: 'cache-and-network' // 先显示缓存,再用网络数据更新;或者用'network-only'直接跳过缓存 });
总结
优先推荐第二种方案——让组件A订阅Link State的变量变化,这是最符合Apollo设计理念的方式,能自动响应状态变化。如果还是有问题,再检查查询配置是否匹配、缓存策略是否正确。
内容的提问来源于stack exchange,提问作者Charlie Lukman
相关产品推荐
相关产品推荐

