当 graphql 变量的状态发生变化时,react-native 上的结果保持不变

Posted

技术标签:

【中文标题】当 graphql 变量的状态发生变化时,react-native 上的结果保持不变【英文标题】:When state changes for graphql variable, result stays the same on react-native 【发布时间】:2020-10-17 14:52:48 【问题描述】:

我正在尝试使用 shopify graphql api 创建一个应用程序,以在 react native expo 上创建一个电子商务应用程序。

我有一个 onPress 调用 setState 来更改 graphQL 变量的状态,但结果不会从 'currentSubCategories' 的初始状态改变


   const [currentSubCategories, setSubCategories] = useState(Categories[0].subCategory[0].handle);
    
      let 
        collection,
        loading,
        hasMore,
        refetch,
        isFetchingMore,
       = useCollectionQuery(currentSubCategories, first, priceRange);

    const [currentCategory, setCategory] = useState(categories: Categories[0]);


    const onSubCategorySelect = (subCategory) =>  setSubCategories(subCategory.handle) 

    onPress=() => onSubCategorySelect(item)

    function useCollectionQuery(
      collectionHandle: string,
      first: number,
      priceRange: [number, number],
    ) 
      let [isInitFetching, setInitFetching] = useState<boolean>(true);
      let [isReloading, setIsReloading] = useState<boolean>(true);
      let [collection, setCollection] = useState<Array<Product>>([]);
      let isFetchingMore = useRef<boolean>(false);
      let hasMore = useRef<boolean>(true);
    
      let defaultCurrency = useDefaultCurrency().data;
    
      let  data, loading, refetch: refetchQuery  = useQuery<
        GetCollection,
        GetCollectionVariables
      >(GET_COLLECTION, 
        variables: 
          collectionHandle,
          first,
          sortKey: ProductCollectionSortKeys.BEST_SELLING,
          presentmentCurrencies: [defaultCurrency],
        ,
        notifyOnNetworkStatusChange: true,
        fetchPolicy: 'no-cache',
      );
    
      let getMoreUntilTarget = async (
        targetAmount: number,
        cursor: string | null,
        handle: string,
        filter: [number, number],
      ) => 
        let result: Array<Product> = [];
        let moreData: Array<Product> = [];
    
        let  data  = await refetchQuery(
          first,
          collectionHandle: handle,
          after: cursor,
        );
    
        ...
    
      useEffect(() => 
        if (!loading) 
          isFetchingMore.current = false;
        
        if (isInitFetching && !!data && !!data.collectionByHandle) 
          let newCollection = mapToProducts(data.collectionByHandle.products);
          hasMore.current = !!data.collectionByHandle?.products.pageInfo
            .hasNextPage;
          setCollection(newCollection);
          setIsReloading(false);
          setInitFetching(false);
        
      , [loading, isInitFetching]); // eslint-disable-line react-hooks/exhaustive-deps
    
      return 
        collection,
        loading: isReloading,
        hasMore: hasMore.current,
        isFetchingMore: isFetchingMore.current,
        refetch,
      ;
    

我正在使用 flatList 来显示结果

    <FlatList
        data=collection
        renderItem=( item ) => (
           <Text>item.title</Text>
        )
    />

【问题讨论】:

【参考方案1】:

根据docs 您必须传递新变量才能重新获取,否则重新获取将使用初始值

在这种情况下(自定义挂钩),您有两种方法可以解决此问题:

从您的自定义挂钩中返回variables(取自useQuery), 返回一些自己的refetch 函数。

第一个选项需要“手动”variables 更新,如:

refetch(  ...variablesFromHook, collectionHandle: currentSubCategories  );

在第二种情况下,您可以创建myRefetch(并返回为refetch),使用collectionHandle 参数调用refetch 并使用更新的变量 - 在您的钩子中隐藏“复杂性”。

这两种情况都需要在更新状态后调用 refetch (setSubCategories) 所以你应该在 useEffect 中使用这个 refetch[currentSubCategories] 依赖......或者干脆不要使用状态,直接从事件处理程序调用refetch(在onSubCategorySelect中)。

【讨论】:

感谢您的帮助,我现在遇到一个问题,尽管将新变量传递给重新获取,但返回的数据与之前的结果相同。我在重新获取变量之前检查了变量的控制台日志,并且它已更改为新变量。不明白为什么它仍然给我同样的结果 使用开发工具/网络或使用graphiql检查'原始'API响应,您也可以console.logonCompleted钩子中收到数据 除非我再次重新获取它,否则返回的结果与之前的结果相同。即使我用不同的变量重新获取,返回的结果总是落后一步,是不是和 async/await 有关系? 检查网络请求(确保使用了新的/更新的变量)......但是有很多与refetch相关的问题,许多关闭仍然报告失败-在github上搜索 发生了一些奇怪的事情。查看网络请求,它实际上进行了两次重新获取,第一个是前一个变量,第二个是当前变量。但是结果还是从第一次refetch开始

以上是关于当 graphql 变量的状态发生变化时,react-native 上的结果保持不变的主要内容,如果未能解决你的问题,请参考以下文章

当 ref 随 vue 组合 api 发生变化时,如何触发 graphql 查询?

如何使用 Apollo/GraphQL 使派生状态保持最新?

反应状态更新不正确

为啥当我追加到其中的列表时,元组的内容会发生变化,但在更新变量时不会发生变化?

当状态随 Provider 发生变化时,使用 StatelessWidget 是不是安全?

当节点后端(MongoDB)中的状态发生变化时通知 Angular 前端