为什么React-Query缓存在React-Native应用程序中的启动过程中不持久化?

kse8i1jr  于 2023-10-22  发布在  React
关注(0)|答案(1)|浏览(137)

我找不到太多关于tanstack的GitHub问题、博客文章或YouTube视频的信息
作为故障排除步骤,我曾尝试使用react查询缓存的默认键记录来自datac-storage的结果,但没有任何结果返回,总是未定义的
我已经按照文档配置了一个mixc存储持久化器,但是在冷启动过程中似乎没有什么东西是持久化的。在下面的仅限客户端的缓存示例中,在其创建时,它存在,但如果硬盘退出多任务并重新打开,则该高速缓存数据未定义
下面是我的查询客户端配置:https://pastebin.com/wMdcHxsz

import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MutationCache, QueryClient } from '@tanstack/react-query'
import { CrashReporting } from 'instabug-reactnative';
 
export const persister = createAsyncStoragePersister({
  storage: AsyncStorage,
  throttleTime: 500,
  key: "REACT_QUERY_OFFLINE_CACHE",
});
 
export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      networkMode: 'online',
      staleTime: Infinity,
      cacheTime: Infinity, // 24 hours
      // staleTime: Infinity, // longer staleTimes result in queries not being re-fetched as often
      refetchOnReconnect: 'always',
      retry: 3,
      retryDelay: 3000,
      refetchOnWindowFocus: true,
      refetchOnMount: true
    },
    mutations: {
      cacheTime: Infinity,
    }
  },
  mutationCache: new MutationCache({
    onSuccess: (data) => {
      console.log('[ Mutation Cache Processed ]:', data)
    },
    onError: (error) => {
      console.log('[ Mutation Cache Error ]:', error)
      CrashReporting.reportError(error);
      throw error
    }
  })
});

下面是我的App.tsx(sans imports):https://pastebin.com/WPkgWLMJ

function App(): JSX.Element {
  useEffect(() => {
    SplashScreen.hide();
 
    onlineManager.setEventListener((setOnline) => {
      return NetInfo.addEventListener((state) => {
        setOnline(!!state.isConnected);
      });
    });
  }, []);
 
  return (
    <ThemeProvider theme={theme}>
      <DevToolProvider>
        <QueryErrorResetBoundary>
          {({ reset }) => (
            <ErrorBoundary onReset={reset}>
              <PersistQueryClientProvider
                client={queryClient}
                persistOptions={{
                  persister,
                  maxAge: Infinity
                }}
                onSuccess={() => {
                  // resume mutations after initial restore from localStorage was successful
                  queryClient.resumePausedMutations().then(() => {
                    queryClient.invalidateQueries();
                  });
                }}>
                <NavigationContainer
                  ref={navigationRef}
                  fallback={
                    <View
                      style={{
                        justifyContent: 'center',
                        alignItems: 'center'
                      }}>
                      <ActivityIndicator animating={true} />
                    </View>
                  }>
                  <RootNavigator />
                </NavigationContainer>
                <ConnectionLostAlert />
                <EnvFlag />
              </PersistQueryClientProvider>
            </ErrorBoundary>
          )}
        </QueryErrorResetBoundary>
      </DevToolProvider>
    </ThemeProvider>
  );
}
 
export default CodePush(codepushConfig)(App);

以下是设置仅限客户端的查询缓存(没有API调用会重置此缓存)的示例:

import { useMutation, useQueryClient } from '@tanstack/react-query';
import { QueryKeys } from '../queries/queryKeys';
import { ProjectJob } from '../ProjectJobsService/types';

export default function useCreateMissingPhotos() {
  const queryClient = useQueryClient();

  queryClient.setMutationDefaults([QueryKeys.MissingPhotos], {
    mutationFn: async () => {} // This is a client-only cache, we don't want to do anything when network is restored
  });

  return useMutation({
    mutationKey: [QueryKeys.MissingPhotos],
    onMutate: async (data: ProjectJob) => {
      await queryClient.cancelQueries([QueryKeys.MissingPhotos]);

      const previousState = queryClient.getQueryData([QueryKeys.MissingPhotos]);

      queryClient.setQueryData(
        [QueryKeys.MissingPhotos],
        (old: ProjectJob[] | undefined) => (old ? [...old, data] : [data])
      );

      return { previousState };
    },
    onError: (err, newState, context) => {
      queryClient.setQueryData(
        [QueryKeys.MissingPhotos],
        context?.previousState
      );
    },
    onSettled: (data, error, newState) => {
      queryClient.invalidateQueries({
        queryKey: [QueryKeys.MissingPhotos]
      });
    }
  });
}

不知道这里出了什么问题,任何建议将不胜感激

gcmastyq

gcmastyq1#

在React Native环境中跨应用启动持久化React Query的缓存需要正确设置React Query的异步存储沿着。根据您的配置,您已经尝试为此目的设置@tanstack/query-async-storage-persister,这是一个很好的步骤。
但是,如果该高速缓存没有在启动时持久化,请首先检查Async Storage是否在React Native项目中正确安装和配置。独立于React Query测试异步存储可能会有所帮助,以确认它是否按预期工作。检查@react-native-async-storage/async-storage是否安装在您的项目中(项目目录中的npm list @react-native-async-storage/async-storageyarn list --pattern @react-native-async-storage/async-storage)。
创建一个简单的函数来设置、获取和删除异步存储中的值。
例如:

import AsyncStorage from '@react-native-async-storage/async-storage';

async function testAsyncStorage() {
  try {
    // Set a value
    await AsyncStorage.setItem('testKey', 'testValue');
    console.log('Value set successfully');

    // Get the value
    const value = await AsyncStorage.getItem('testKey');
    console.log('Retrieved value:', value);  // Should log: 'Retrieved value: testValue'

    // Remove the value
    await AsyncStorage.removeItem('testKey');
    console.log('Value removed successfully');

    // Try to get the value again (should be null)
    const nullValue = await AsyncStorage.getItem('testKey');
    console.log('Value after removal:', nullValue);  // Should log: 'Value after removal: null'

  } catch (error) {
    console.error('Async Storage test failed:', error);
  }
}

// Call the function to test Async Storage
testAsyncStorage();

之后:

  • createAsyncStoragePersister方法中,您指定了"REACT_QUERY_OFFLINE_CACHE"key。确保此密钥不会与应用程序中异步存储中使用的任何其他密钥冲突。
  • 在您的queryClient配置中,您已将cacheTime设置为Infinity。虽然这应该将数据保留在缓存中,但可能值得尝试使用有限值来观察任何不同的行为。
  • PersistQueryClientProvider中,您已将maxAge设置为persistOptions中的Infinity。与cacheTime设置类似,您可能希望对有限值进行试验。
  • QueryClientPersistQueryClientProvider上下文之外测试persister,以确保它按预期运行。您可能希望手动与persister交互,以便将测试对象保存到AsyncStorage,或从AsyncStorage检索测试对象。
  • 检查mutationCacheuseMutation钩子中的错误处理逻辑是否存在任何问题。

上述所有工作已经完成:persistQueryClient在其他领域也可以工作,我已经为maxAge/CacheTime使用了有限的值,我也尝试过在应用程序挂载时手动调用persistQueryClient。上面提到的查询缓存似乎不受交叉启动的影响。
考虑到Async Storage在应用程序的其他区域正常运行,并且已经测试了maxAgecacheTime的各种配置,并且在应用程序挂载时尝试手动调用persistQueryClient没有成功,这应该意味着可能存在与React Query和Async Storage之间的交互相关的问题。
首先查看PersistQueryClientProviderQueryClient的配置,以确保它们与React Query和@tanstack/query-async-storage-persister提供的文档和示例保持一致。
我假设你有最新的稳定版本,特别是@tanstack/react-query@tanstack/query-async-storage-persister@react-native-async-storage/async-storage
检查从该高速缓存存储和检索的数据是否正确地序列化和重新序列化。存储在异步存储中的数据需要在检索时进行字符串化和正确解析。
我还将记录保存到异步存储和从异步存储检索的数据,以查看它是否按预期存储和检索。这包括在持久化数据之前和检索数据之后立即检查数据。
如果问题仍然存在,请尝试创建一个具有最小配置的简化场景,以测试React Query缓存在应用启动过程中的持久性:这应该有助于隔离问题。

相关问题