Not able to get Relay work with React Native - react-native

I'm trying to setup a basic React Native Relay project. I'm creating this issue after spending ample of time trying debug the problem without any luck. I'm getting this warning on console and my react native app is not able to make calls to GraphQL server.
Warning: RelayNetworkLayer: Call received to injectImplementation(), but a layer was already injected.
Running application "ExampleApp" with appParams: {"rootTag":1,"initialProps":{}}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
fetchWithRetries(): Still no successful response after 1 retries, giving up.
Here is my code
index.ios.js
import React, { Component } from 'react';
import Relay from 'react-relay';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import App from './app';
import AppRoute from './route/appRoute';
Relay.injectNetworkLayer(
new Relay.DefaultNetworkLayer("http://localhost:1337/graphy")
);
class ExampleApp extends Component {
render() {
return (
<Relay.RootContainer
Component={App}
route={new AppRoute()}
/>
);
}
}
AppRegistry.registerComponent('ExampleApp', () => ExampleApp);
appRoute.js
'use strict';
import Relay from 'react-relay';
export default class extends Relay.Route {
static queries = {
page: (Component) => Relay.QL`
query {
posts(offset: 0) { ${Component.getFragment('page')} }
}
`,
};
static routeName = 'AppRoute';
}
app.js
'use strict';
import React, {Component} from 'react';
import Relay from 'react-relay';
import {
View,
Text,
} from 'react-native';
class App extends Component {
render() {
console.log('props', this.props);
return(
<View>
<Text>Testing</Text>
</View>
);
}
}
export default Relay.createContainer(App, {
fragments: {
page: () => Relay.QL`
fragment on Viewer {
posts { id, title }
}
`,
}
});
package.json
{
"name": "ExampleApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"babel": "^6.5.2",
"babel-preset-react-native": "^1.8.0",
"babel-relay-plugin": "^0.8.1",
"react": "^0.14.8",
"react-native": "^0.25.1",
"react-relay": "^0.8.1"
}
}
babelRelayPlugin.js
const getBabelRelayPlugin = require('babel-relay-plugin');
const schema = require('../schema.json');
module.exports = { plugins: [getBabelRelayPlugin(schema.data)] };
Here is the full repo link: https://github.com/popstand/react-native-relay-graphql-example
Similar code built with ReactJS and Relay works well on webpage. I'm not able to make it work on React Native. What is possibly going wrong here which is causing this issue?

I would suggest you may check out the F8 App by Facebook. There is definitely a setup script, a main route, a relay container and a schema to be seen.

It's possible that your GraphQL server is returning a bad response. This happened to me and I solve with debug the server (with this).
You can see the code of this example app in: https://github.com/danielfeelfine/react-native-relay

Related

Exception: Property 'GraphQLError' doesn't exist

I'm trying to use GraphQL with Apollo and repack in my sample react native app. However, when I run the app in the simulator, I receive this error of GraphQLError not existing. If I comment out all the Apollo code in App.tsx, the app works just fine. Does anyone have any insight on if I'm using the webpack.configure.js incorrectly, or if I have an error in my code?
App.tsx
import { Federated } from '#callstack/repack/client';
import React from 'react';
import { ScrollView, Text, AppRegistry } from 'react-native';
import { ApolloProvider } from '#apollo/client';
import { ApolloClient, InMemoryCache, ApolloProvider } from '#apollo/client';
const App1 = React.lazy(() => Federated.importModule('app1', './App'));
// Initialize Apollo Client
const client = new ApolloClient({  uri: 'localhost:4000/graphql',  cache: new InMemoryCache()});
export default function App() {
return (
<ApolloProvider client={client}>
<ScrollView> <Text> Hello World</Text></ScrollView>
   <App1 />
</ApolloProvider>
);
}
webpack.config.js
rules: [{
test: /\.[jt]sx?$/,
include: [
/node_modules(.*[/\\])+react/,
/node_modules(.*[/\\])+#react-native/,
/node_modules(.*[/\\])+#react-native-community/,
/node_modules(.*[/\\])+#expo/,
/node_modules(.*[/\\])+pretty-format/,
/node_modules(.*[/\\])+metro/,
/node_modules(.*[/\\])+abort-controller/,
/node_modules(.*[/\\])+#callstack\/repack/,
/node_modules(.*[/\\])+#apollo\/client/,
/node_modules(.*[/\\])+graphql/,
/node_modules(.*[/\\])+core-js-pure/,
],
use: 'babel-loader',

Not able to install Native Base in my react prject

Does using expo react native doesn't allow to install native base ?
It is documented in nativebase website. You will have to install expo-font and make some adjustments in App.js. The official documentation link is https://docs.nativebase.io/docs/GetStarted.html#Setup_with_Expo
No, expo doesn't stop you from using any frontend package, because there is a specific way to install native base after installing native-base. Put the following code in your main react-native file
import React, { Component } from 'react';
import { Root } from 'native-base';
import Main from "project directory";
import * as Font from 'expo-font';
import { ActivityIndicator } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
async componentDidMount() {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
});
this.setState({ loading: false });
}
render() {
if (this.state.loading) {
return (
<Root>
<ActivityIndicator />
</Root>
);
} else {
return (
<Root>
<Main/>//Your main Javascript project file.
</Root>
);
}
}
}

Exception in HostFunction: <unknown> when trying to push new screen

Issue Description
Trying to push a new screen with
Navigation.push(this, {
component: {
name: 'awesome-places.AuthScreen' }})
And getting an error Exepction in HostFunction <unknown>
Error Screenshot
Steps to Reproduce / Code Snippets / Screenshots
Create RN app, install required modules (redux, react-redux, react-native-navigation, react-vector-icons) and run code on Android device.
Add relevant code, App.js and component that causes the error. I tried running Navigation.push with this.props.componentId but when I press the button there is no response
App.js
import { Navigation } from 'react-native-navigation';
import { Provider } from 'react-redux';
import AuthScreen from './src/screens/Auth/Auth';
import SharePlaceScreen from './src/screens/SharePlace/SharePlace';
import FindPlaceScreen from './src/screens/FindPlace/FindPlace';
import PlaceDetailScreen from './src/screens/PlaceDetail/PlaceDetail';
import configureStore from './src/store/configureStore';
const store = configureStore();
// Register Screens
Navigation.registerComponentWithRedux("awesome-places.AuthScreen", () => AuthScreen, Provider, store);
Navigation.registerComponentWithRedux("awesome-places.SharePlaceScreen", () => SharePlaceScreen, Provider, store);
Navigation.registerComponentWithRedux("awesome-places.FindPlaceScreen", () => FindPlaceScreen, Provider, store);
Navigation.registerComponent("awesome-places.PlaceDetailScreen", () => PlaceDetailScreen);
// Start an App
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot({
root: {
component: {
name: 'awesome-places.AuthScreen'
}
}
});
});
FindPlace.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { connect } from 'react-redux';
import { Navigation } from 'react-native-navigation';
import PlaceList from '../../components/PlaceList/PlaceList';
class FindPlaceScreen extends Component {
Navigation.push(this, {
component: {
name: 'awesome-places.AuthScreen',
}
})
}
render () {
return(
<View>
<PlaceList places={this.props.places} onItemSelected={this.itemSelectedHandler} />
</View>
);
}
}
const mapStateToProps = state => {
return {
places: state.places.places
}
}
export default connect(mapStateToProps)(FindPlaceScreen);
Environment
React Native Navigation version: 2.17.0
React Native version: 0.59.4
Platform(s) (iOS, Android, or both?): Android
Device info (Simulator/Device? OS version? Debug/Release?): Android 7.1.2, Debug
I noticed you're pushing the screen with this instead of an explicit componentId.
When calling Navigation.push, the first argument needs to be a componentId. See the docs for reference.
Also, this might not be a problem, but registerComponentWithRedux is deprecated and you should register the screen with the new api

How to authorize users across the react-navigation app?

I have 2 groups of screens in my app.
1) AuthorizedScreens
2) NotAuthorizedScreens
As soon as the app loads I want to check if the user is logged in or not? If the user is logged in, the app loads AuthorizedScreens and if not, It loads NotAuthorizedScreens. How do i achieve this? I have included a sample of not working code but I guess that's how it could be!
App.js
import React from 'react';
import { AsyncStorage } from 'react-native';
import { Provider } from 'react-redux';
import { DrawerNavigator, StackNavigator } from 'react-navigation';
import store from './store';
export default class App extends React.Component {
async componentWillMount() {
const token = await AsyncStorage.getItem('facebook_token');
}
render() {
const AuthorizedScreens = DrawerNavigator(...
const NotAuthorizedScreens = DrawerNavigator(...
return (
<Provider store={store}>
{ (this.token) ? <AuthorizedScreens /> : <NotAuthorizedScreens /> }
</Provider>
);
}
}
Note!
I have an action creator that checks if the user is logged in. But I couldn't connect it to the App component, therefore I decided to use AsyncStorage to store a facebook_token, and if the token exist means user is logged in and if not the user is not...
"dependencies": {
"expo": "^20.0.0",
"react": "16.0.0-alpha.12",
"react-native": "https://github.com/expo/react-native/archive/sdk-20.0.0.tar.gz",
"react-navigation": "^1.0.0-beta.11",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0"
}
I have solved this issue by setting a state in componentWillMount and calling it from return.
import React from 'react';
import { AsyncStorage } from 'react-native';
import { Provider } from 'react-redux';
import { DrawerNavigator, StackNavigator } from 'react-navigation';
import store from './store';
export default class App extends React.Component {
state = {
login_token: '',
};
async componentWillMount() {
const token = await AsyncStorage.getItem('facebook_token');
this.setState({ login_token: token });
}
render() {
const AuthorizedScreens = DrawerNavigator(...
const NotAuthorizedScreens = DrawerNavigator(...
return (
<Provider store={store}>
{ (this.state.login_token) ? <AuthorizedScreens /> : <NotAuthorizedScreens /> }
</Provider>
);
}
}
I have solved this problem, but I am not sure if I did it the right way! Because, Redux is in charge of my state management, but I manually used the react state management by setting state.
I will appreciate your inputs if you know a better way.

How do I debug "Objects are not valid as a React child" react native error

Objects are not valid as a React child (found: object with keys {style, title}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of View.
I don't know what to make of the trace I've pasted, because it's not in my code at all. Any ideas would be greatly appreciated! Thanks.
Trace on simulator
index.ios.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Navigator
} from 'react-native';
import Product from './product.js';
import Services from './services.js';
import ProductsList from './productslist.js';
import AddProduct from './addProduct.js';
import {StackNavigator} from 'react-navigation';
const routes = [
{
title : 'Services',
renderFunc : (navigator) => <Services navigator={navigator} />
},
{
title : 'Marketplace',
renderFunc : (navigator) => <ProductsList navigator={navigator}/>
}
];
const stackNavigatorRoutes = {
Services : {
screen : Services,
},
ProductsList : {
screen : ProductsList
},
Product : {
screen : Product
},
AddProduct : {
screen : AddProduct
}
};
const AppNavigator = StackNavigator({
...stackNavigatorRoutes,
},
{
initialRouteName : 'Services',
navigationOptions : {
header : {
style : {
height : 60,
backgroundColor : 'cadetblue'
},
title : 'ResiShare'
}
}
});
class Rs extends Component {
render() {
return (
<AppNavigator />
// <ProductsList />
// <AddProduct />
);
}
}
The main point of my question was to figure out to debug something like this where the trace doesn't show any of my code.
The answer was to just replace entry point in index.ios.js with something that works and then slowly add back components.
In this particular case, the reason for this fubar-ing was a breaking change from react-navigation (https://github.com/react-community/react-navigation/issues/1413) that I didn't realize I had picked up (I definitely must've done an npm install).