Why does useQuery not work but client.query does? - react-native

I am struggling to get ApolloClient useQuery to work in a simple react native application. Using Flipper, I can see that the useQuery does not even create a hit on the graphql endpoint. In debugging this, I tried to use ApolloClient's client.query as an alternative means of making the graphql query and it worked! So I am confused about why useQuery is not working.
Here is the entire App.js code that shows client.query working but useQuery failing to fetch. And a screenshot of the resulting app. I'd really appreciate if someone could tell me where I'm going wrong.
import React, {useState} from 'react';
import {Text, View} from 'react-native';
import {ApolloClient,InMemoryCache,ApolloProvider,gql,useQuery} from '#apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:8000/graphql',
cache: new InMemoryCache(),
});
const ALL_AREAS = gql`
query AllAreas {
allAreas {
id
name
}
}
`;
// Using client.query to make graphql query
function Areas1() {
const [data, setData] = useState('Loading ...');
client
.query({
query: ALL_AREAS,
})
.then(result => {
console.log('Areas 1 Data: ', result.data);
setData('Data ...');
});
return <Text>{data}</Text>;
}
// Using react-hook to make graphql query
function Areas2() {
const {loading, error, data} = useQuery(ALL_AREAS);
if (loading) {
return <Text>Loading ...</Text>;
}
if (data) {
console.log('Areas 2 Data: ', data);
return <Text>Data ...</Text>;
}
}
const App = () => {
return (
<ApolloProvider client={client}>
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Hello World {'\n'}</Text>
<Text>
client.query: <Areas1 />
</Text>
<Text>
useQuery: <Areas2 />
</Text>
</View>
</ApolloProvider>
);
};
export default App;
Note: I included console log statements and noticed that the console log from the Areas2 component never fires, whereas the console log from Areas1 does fire and shows the fetched data.
The resulting app in my emulator looks like this:
I am using the following package versions:
"#apollo/client": "^3.6.2",
"graphql": "^16.5.0",
"react": "17.0.2",
"react-native": "0.68.2"

I had some issue with #apollo/client v3.6.2 and have been trying to find the solution. But now you can check on #apollo/client (v3.6.4) for a new realise which is solving the query issue.
Uninstall #apollo/client 3.6.2
npm uninstall #apollo/client or yarn remove #apollo/client
Now install the new realise #apollo/client 3.6.4
npm install #apollo/client or yarn add #apollo/client
Then stop the metro bundler and run the app again
ios: npm run ios or yarn ios
android: npm run android or yarn android

Related

Error: Requiring module "node_modules\react-native-reanimated\src\Animated.js",

I am trying to use createDrawerNavigator from import { createDrawerNavigator } from '#react-navigation/drawer'; in react native. However, I am getting the error below, which I don't know how to solve.
Error: Requiring module
"node_modules\react-native-reanimated\src\Animated.js", which threw an
exception: Error: Reanimated 2 failed to create a worklet, maybe you
forgot to add Reanimated's babel plugin?
In babel.config.js I tried to add the below code but not working as well
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
'react-native-reanimated/plugin',
]
};
};
The Below code is my component
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function MyDrawer() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Please complete the setup for react-native-reanimated.
You have to add 'react-native-reanimated/plugin', in the babel.config.js file so the final code in babel.config.js will look like
module.exports = {
...
plugins: [
...
'react-native-reanimated/plugin',
],
};
As state in the setup docs for react-native-reanimatedHere
Also you need to complete setup for android as well (if not done yet) as stated Here
If you are using expo then follow these steps
Finally, run expo r -c to clear the cache.
If you are using expo. Set this in babel.config.js:
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'],
};
};
Note: If you load other Babel plugins, the Reanimated plugin has to be the last item in the plugins array
After you add the Babel plugin, restart your development server and clear the bundler cache: expo start --clear.
You must install according to these instructions:
[https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation/][1]
Also, make no mistake Be careful where you write the following code
#Override
protected JSIModulePackage getJSIModulePackage() {
return new ReanimatedJSIModulePackage(); }
[Solution][1]
yarn add react-native-reanimated
cd ios
pod install
And Import on either Index or App .js file
import Animated from 'react-native-reanimated';
[1]: https://docs.swmansion.com/react-native-reanimated/docs/1.x.x/getting_started/
I am using react-native 0.69.3 and also had an issue with compiling reanimated#2.10. I updated to #2.11.0 and it fixed my compile error.
Make sure react-native-reanimated is up to date and the other packages are the same then try running npx react-native link react-native-reanimated.
If that didn't work you need to set up react-native-reanimated properly. Check out the documentation on how to set it up.
According to react navigations drawer documentation.
After installing all the packages
To finalize installation of react-native-gesture-handler, add the following at the top (make sure it's at the top and there's nothing else before it) of your entry file, such as index.js or App.js:
import 'react-native-gesture-handler';
Now this might now work for you. To complete the installation you have to change your babel.config.js file add the following:
plugins: [...,"react-native-reanimated/plugin"]
Note ... just means your other plugins if you have. Remove it if you don't have any.
You are almost there. The final thing you have to know and do is:
Note: If you load other Babel plugins, the Reanimated plugin has to be
the last item in the plugins array.
After you add the Babel plugin, restart your development server and
clear the bundler cache: expo start --clear
You can reference the expo reanimated docs for more details
Add this to babel.config.js file:
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'],
};
then run this to clear cache and restart development server:
npx expo start --clear
learn more on expo official doc.

expo-asset useAssets hook returns undefined while there is cached image on the disk

When internet access is on, useAssets returns the localUri as expected. But after going offline, it returns undefined. Even the cached file still exists in the cache folder, it does not reference it. The code is below:
import React from "react";
import { useAssets } from "expo-asset";
import { Image, View } from "react-native";
export default function Avatar({ imageUrl}) {
const [assets, error] = useAssets([imageUrl]);
return (
<View style={[styles.avatar, style]}>
<Image
source={{
uri: assets[0].localUri
}}
/>
</View>
);
}
So I want to access downloaded and cached images offline with useAssets hook but it seems that expo-assets has not such feature, isn't it?
You need to install the 'expo-asset' package.
expo install expo-asset

Unable to resolve "./rules/FieldsOnCorrectType" from "node_modules/graphql/validation/index.js"

I'm building a react native application with apollo client 3, and keep getting the following error when generating the javascript bundle.
Failed building JavaScript bundle.
Unable to resolve "./rules/FieldsOnCorrectType" from "node_modules/graphql/validation/index.js"
My code is pretty simple, this is App.tsx:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import useCachedResources from './hooks/useCachedResources';
import useColorScheme from './hooks/useColorScheme';
import Navigation from './navigation';
import { ApolloClient, InMemoryCache, ApolloProvider } from '#apollo/client';
const client = new ApolloClient({
uri: 'localhost:4000/graphql',
cache: new InMemoryCache()
});
export default function App() {
const isLoadingComplete = useCachedResources();
const colorScheme = useColorScheme();
if (!isLoadingComplete) {
return null;
} else {
return (
<ApolloProvider client={client}>
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar />
</SafeAreaProvider>
</ApolloProvider>
);
}
}
I've tracked it down to the instantiation of the new ApolloClient object - commenting out those lines (and the provider) causes the error to disappear.
Renaming node_modules/graphql/validation/rules/FieldsOnCorrectTypeRule.js to node_modules/graphql/validation/rules/FieldsOnCorrectType.js (dropping the Rule suffix of filename) fixes that specific error, but then errors on the next import in the validation/index.js file... I don't understand why.
I had the same problem with a react native app after upgrading to apollo client 3. For me it was a react native caching issue and the problem went away after following these instructions to clear the cache: How to clear react-native cache?.
I am using the react native cli and used these commands (I didn't check if all of them are actually necessary):
watchman watch-del-all
rm -rf /tmp/metro-cache
rm -rf node_modules
npm cache clean --force
npm install
npm start -- --reset-cache
If you are using the expo cli then apparently you can just do this:
expo start -c

React Native:Module RCTEventEmitter is not a registered callable module (calling receiveTouches)

I am trying to work with react-navigation, but have some problems. I cant see what is wrong. How can I solve this problem?
What I have tried so far:
Restarted emulator (PC)
Rewrite all code
Created new a project and tried that code there too.
import React, {Component} from 'react';
import {StyleSheet,Text,View} from 'react-native';
import {createStackNavigator,createAppContainer} from "react-navigation";
class HomeScreen extends Component {
render() {
return (
<View style={styles.container}>
<Text>Home</Text>
</View>
);
}
}
export default class App extends Component{
render(){
return(
<AppContainer />
);
}
}
const AppNavigator = createStackNavigator({
Home:{
screen: HomeScreen
}
});
const AppContainer = createAppContainer(AppNavigator);
const styles=StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems:'center',
backgroundColor:'#F5FCFF',
}
});
Starting from 0, this is what i did:
1) react-native init navigation
2) cd navigation
3) npm i react-navigation
4) npm i react-native-gesture-handler
5) Copied your code inside App.js
6) react-native start --reset-cache
7) react-native run-android
My android simulator is a Nexus 5X API 28 X86 and works as expected.
Hope this helps you resolve this problem!
Just Use
index.ios.js
or
index.andriod.js.
I was facing the same issue, as you can see in the screenshot (below) of my debugger; for that, I closed the metro bundler and then re-run the app in the terminal. It works for me.
your importing createStackNavigator from the wrong pkg, you need to install react-navigation-stack and then import createStackNavigator from that pkg... hopes this solves your problem

How to check for an internet connection in an Expo React Native app?

I have an Expo app using the Managed workflow. The app needs to check whether an internet connection is available.
I can't import { NetInfo } from 'react-native' because that's deprecated.
I can't use react-native-community/react-native-netinfo because that uses native libraries, and you can't do that with an Expo managed app.
I could eject, in order to use the above, but it doesn't seem like I should need to do that just to check if there's an internet connection.
I can't use navigator.onLine because that global variable doesn't seem to be available.
I could make a trivial HTTP request to Google or my own server or whatever, and see if I get a response, but that only tests a connection to one site, and also it takes time and uses bandwidth.
What should I do?
Expo SDK 34 has already included NetInfo API.
You can check their documentation for SDK 34 here https://docs.expo.io/versions/v34.0.0/sdk/netinfo
Here is the link for documentation for latest version
Use NetInfo of react-native.
Yes, it is deprecated because they are planning on removing it in the next version of react-native in favor of the community version. However, it is completely functional and can still be used for now, just make sure to check for breaking changes when the next versions of Expo SDK are released.
It is likely that Expo will bring it into their managed workflow when react-native removes it, or provide an alternative that won't require ejecting from Expo.
It's really hard to define if a device has internet or not stackoverflow.com/a/189443/7602110, just by having failed XHR requests you can say that you have internet, but isn't that reliable. You would like to check with some reliables websites like google.com, I have come with a work-around but I don't actually recommend it, is up to you.
You can use the Linking.canOpenUrl() method from React Native itself, which will return a Promise object. When it is determined whether or not the given URL can be handled, the promise is resolved and the first parameter is whether or not it can be opened.
Then add a request and if the response status it's 200 you should have internet.
import React, { Component } from 'react';
import { Button, Text, View, StyleSheet, Linking } from 'react-native';
export default class App extends Component {
state = {
connection: false,
url: 'https://google.com',
};
checkInternt = () => {
Linking.canOpenURL(this.state.url).then(connection => {
if (!connection) {
this.setState({ connection: false });
} else {
fetch(this.state.url).then(res =>
this.setState({ connection: res.status !== 200 ? false : true })
);
}
});
};
componentDidMount() {
this.checkInternt();
}
handlePress = () => {
this.setState({
url:
this.state.url === 'https://google.com'
? 'http://someweirdurlthatdoesntwork.com'
: 'https://google.com',
});
this.checkInternt();
};
render() {
return (
<View style={styles.container}>
<Text>
Connection:
<Text style={{ color: this.state.connection ? 'green' : 'red' }}>
{` ${this.state.connection}`}
</Text>
</Text>
<Text>{this.state.url.replace(/\https?:\/\//g, '')}</Text>
<Button onPress={this.handlePress} title="Change server url" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
});
Check the snack: snack.expo.io/#abranhe/check-internet
2022 here, had the same issue before ejecting expo, we used expo-network
import * as Network from 'expo-network';
and use it like so
const networkState = await Network.getNetworkStateAsync();
I hope this helps someone!