query: React Native: Queries not executing on v4

Describe the bug

Hi,

I’m trying out 4.0.0-beta.7 to implement offline support in our application.

Everything is upgraded including all the breaking changes, but my queries are not being executed anymore. To be sure it’s not a problem inside my application, I’ve created a fresh expo app with just the App.tsx file.

When opening the app, my queries remain in a loading state. If I use the refetch of the useQuery, and run this in a useEffect, I’m able to execute the query.

Your minimal, reproducible example

Couldn’t get react-query to work in expo snack

Steps to reproduce

  1. Create a react-native application with the following package.json file
{
  "name": "reactqueryv4",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "~44.0.0",
    "expo-status-bar": "~1.2.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "react-native": "0.64.3",
    "react-native-web": "0.17.1",
    "react-query": "4.0.0-beta.7"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~17.0.21",
    "@types/react-native": "~0.64.12",
    "typescript": "~4.3.5"
  },
  "private": true
}
  1. Create a query with a simple async function
import { Text, View } from "react-native";
import { QueryClient, QueryClientProvider, useQuery } from "react-query";

export default function App() {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <Todos />
    </QueryClientProvider>
  );
}

function Todos() {
  // Queries
  const query = useQuery(["todos"], async () => {
    console.log("this should log but doesn't");

    return Promise.resolve("ok");
  });

  console.log(query.data);

  return (
    <View>
      <Text>lol</Text>
    </View>
  );
}
  1. Open your application and you will see undefined query data, a status loading and no console.log.

Expected behavior

I expect this query to be executed. If I change my package.json to the latest v3 version, my query get’s executed as it should.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • iOS, Android

react-query version

4.0.0-beta.7

TypeScript version

No response

Additional context

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 4
  • Comments: 34 (23 by maintainers)

Most upvoted comments

This line in useBaseQuery imports useSyncExternalStore like this:

import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"

If you change it to following, it works:

import { useSyncExternalStore } from "use-sync-external-store/shim"

The shim folder does include a different file for React Native (index.native.js). If we look at contents in the repo, those files are identical, but they differ in the published package.

The code of index.js in the published package:

'use strict';

if (process.env.NODE_ENV === 'production') {
  module.exports = require('../cjs/use-sync-external-store-shim.production.min.js');
} else {
  module.exports = require('../cjs/use-sync-external-store-shim.development.js');
}

The code of index.native.js in published package:

'use strict';

if (process.env.NODE_ENV === 'production') {
  module.exports = require('../cjs/use-sync-external-store-shim.native.production.min.js');
} else {
  module.exports = require('../cjs/use-sync-external-store-shim.native.development.js');
}

So it doesn’t work because the code isn’t importing the React Native specific implementation.

I added a log here and it doesn’t get called when using use-sync-external-store/shim/index.js but gets called with use-sync-external-store/shim. Though I tried the same code inside App.js but couldn’t reproduce the issue. I guess metro is importing code differently inside node_modules? But it’s pretty confusing why it would do that.

Here is a video showing that this change works:

https://user-images.githubusercontent.com/1174278/167318631-9b18e5a9-c7f4-4368-adfd-3a18853c599d.mp4

I see that this change was made in https://github.com/tannerlinsley/react-query/pull/3561 for ESM, so I guess the fix would be for React to add a package.json inside the shim folder so that it can be imported normally, or create 2 new files that have imports for React Native and rest.

My test code:

expo init testapp
cd testapp
yarn add react-query@4.0.0-beta.7

And paste the following in App.js:

import { Text, View } from 'react-native';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';

export default function App() {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <Test />
    </QueryClientProvider>
  );
}

function Test() {
  // Queries
  const query = useQuery(['test'], {
    queryFn: async () => {
      console.log("this should log but doesn't");

      return Promise.resolve('ok');
    },
  });


  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Status: {query.status} </Text>
      <Text>Data: {query.data} </Text>
    </View>
  );
}

🎉 This issue has been resolved in version 4.0.0-beta.10 🎉

The release is available on:

Your semantic-release bot 📦🚀

Ah ok I see what you’re saying now. Yes that would be much simpler. I didn’t realize React Native doesn’t resolve the esm files.

Why not fix it in use-sync-external-store/shim? If every package using it has to do workarounds for using it then it won’t be ideal. It’ll be more beneficial to fix it at the source so that it’s compatible with ESM.

You also don’t need a separate build without an extension or a package.json. If you want to fix it in React Query instead of in use-sync-external-store, then you can create 2 files useSyncExternalStore.js and useSyncExternalStore.native.js that use different imports and exports them, and then you can import ./useSyncExternalStore .

Well, at first my iOS version was also still working. After a clean app install this issue was also happening on iOS. And if you create a fresh react-native project, you will see it happening on both iOS and Android.