undefined is not an object (evaluating 'RNGuestureHandlerModule.state') - reactjs

New to React-Native and when I try and and add the navigation module to my app it breaks.
import React from 'react';
import { createStackNavigator, createAppContainer} from 'react-
navigation';
import { StyleSheet, Platform, Image, Text, View, ScrollView,
TextInput, Button, FlatList } from 'react-native';
import firebase from 'react-native-firebase';
import Todo from './Todo';
class HomeScreen extends React.Component {
constructor() {
super();
this.ref = firebase.firestore().collection('todos');
this.unsubscribe = null;
this.state = {
textInput: '',
loading: true,
todos: [],
};
}
async componentDidMount() {
// TODO: You: Do firebase things
// const { user } = await firebase.auth().signInAnonymously();
// console.warn('User -> ', user.toJSON());
// await firebase.analytics().logEvent('foo', { bar: '123'});
}
componentDidMount() {
this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate)
}
componentWillUnmount() {
this.unsubscribe();
}
updateTextInput(value) {
this.setState({ textInput: value });
}
onCollectionUpdate = (querySnapshot) => {
const todos = [];
querySnapshot.forEach((doc) => {
const { title, complete } = doc.data();
todos.push({
key: doc.id,
doc, // DocumentSnapshot
title,
complete,
});
});
this.setState({
todos,
loading: false,
});
}
addTodo() {
this.ref.add({
title: this.state.textInput,
complete: false,
});
this.setState({
textInput: '',
});
}
render() {
if (this.state.loading) {
return null; // or render a loading icon
}
return (
<View style={{ flex: 1 }}>
<Button
title="Go to Jane's profile"
onPress={() => navigate('Profile', {name: 'Jane'})}
/>
<FlatList
data={this.state.todos}
renderItem={({ item }) => <Todo {...item} />}
/>
<TextInput
placeholder={'Add TODO'}
value={this.state.textInput}
onChangeText={(text) => this.updateTextInput(text)}
/>
<Button
title={'Add TODO'}
disabled={!this.state.textInput.length}
onPress={() => this.addTodo()}
/>
</View>
);
}
}
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen
}
});
export default createAppContainer(AppNavigator);
When I got to run the code I get the error
"undefined is not an object (evaluating 'RNGuestureHandlerModule.state')"
I've tried running the sample code of react navigation and receive the same error.
Wondering if it's issue with my index.js file?
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);

Managed to fix this issue by :
rm -rf node_modules
npm install
npm install react-native-cli
npm install --save react-navigation
npm install --save react-native-gesture-handler
react-native link

Related

React Native / Expo / NativeBase - fontFamily "Roboto_medium" is not a system font and has not been loaded through Font.loadAsync

I am creating a mobile app using Expo and would like to use NativeBase for UI components.
No matter what I try to do I get this annoying error: fontFamily "Roboto_medium" is not a system font and has not been loaded through Font.loadAsync
I had a look at the docs and used the example from there and it works!
import React from 'react';
import { AppLoading } from 'expo';
import { Container, Text } from 'native-base';
import * as Font from 'expo-font';
import { Ionicons } from '#expo/vector-icons';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isReady: false,
};
}
async componentDidMount() {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
});
this.setState({ isReady: true });
}
render() {
if (!this.state.isReady) {
return <AppLoading />;
}
return (
<Container>
<Text>Open up App.js to start working on your app!</Text>
</Container>
);
}
}
Please note how they load the fonts in componentDidMount()
Now, as you can see this is the old React and I would like to use hooks and function components.
I tried this:
useEffect(() => {
(async () => await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
}))();
}, [])
I tried that:
useEffect(async() => {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
});
}, [])
And nothing works for me! Can somebody please help? How can I load those fonts?
First we have to install the expo google font that we want to use, for example:
expo install expo-font #expo-google-fonts/inter expo-app-loading
Next step we create a theme file theme.js for our native-base provider, see reference: https://docs.nativebase.io/next/customizing-fonts
import { extendTheme } from "native-base";
export const theme = extendTheme({
fontConfig: {
Inter: {
400: {
normal: "Inter_400Regular",
},
500: {
normal: "Inter_500Medium",
},
600: {
normal: "Inter_600SemiBold",
},
},
},
fonts: {
heading: "Inter",
body: "Inter",
mono: "Inter",
},
});
Finally, we link our theme file and load the font in to the App file, see reference: https://docs.expo.dev/guides/using-custom-fonts/
import {
useFonts,
Inter_400Regular,
Inter_500Medium,
Inter_600SemiBold
} from "#expo-google-fonts/inter";
import AppLoading from 'expo-app-loading';
import { NativeBaseProvider, Box, Text } from "native-base";
import { theme } from "./theme";
export default function App() {
let [fontsLoaded] = useFonts({
Inter_400Regular,
Inter_500Medium,
Inter_600SemiBold
});
if (!fontsLoaded) {
return <AppLoading />;
}
return (
<NativeBaseProvider theme={theme}>
<Box flex={1} bg="#fff" alignItems="center" justifyContent="center">
<Text fontWeight="500">
Expo Google Font with Native Base
</Text>
</Box>
</NativeBaseProvider>
);
}

ReactNative - invariant violation: requireNativeComponent: "RNCSafeareview" was not found in the UI Manager

I have created a react native package with expo-bare-workflow. I have also added the packages like,
npm install --save react-navigation
npm install --save react-native-gesture-handler
npm install --save react-navigation-stack
npm install --save #react-native-community/masked-view
npm install --save react-native-safe-area-view
npm install --save react-native-safe-area-context
npm install --save react-native-gesture-handler
npm install --save react-native-reanimated
Following is my App.js file.
import React from 'react';
import {
ActivityIndicator,
AsyncStorage,
Button,
StatusBar,
StyleSheet,
Text,
View,
} from 'react-native';
import { createSwitchNavigator, createAppContainer } from 'react-navigation';
import { createStackNavigator } from "react-navigation-stack";
class SignInScreen extends React.Component {
static navigationOptions = {
title: 'Please sign in',
};
render() {
return (
<View style={styles.container}>
<Button title="Sign in!" onPress={this._signInAsync} />
</View>
);
}
_signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate({
routeName: 'Home',
key: 'Home',
params: { userInfo: 'lol' },
});
};
}
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome to the app!',
};
componentDidMount() {
// alert(JSON.stringify(this.props.navigation.state.params))
}
render() {
return (
<View style={styles.container}>
<Text>{JSON.stringify(this.props.navigation.state.params)}</Text>
<Button title="Show me more of the app" onPress={this._showMoreApp} />
<Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
</View>
);
}
_showMoreApp = () => {
this.props.navigation.navigate('Other');
};
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class OtherScreen extends React.Component {
static navigationOptions = {
title: 'Lots of features here',
};
render() {
return (
<View style={styles.container}>
<Button title="I'm done, sign me out" onPress={this._signOutAsync} />
<StatusBar barStyle="default" />
</View>
);
}
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class AuthLoadingScreen extends React.Component {
constructor() {
super();
this._bootstrapAsync();
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away.
if (userToken) {
this.props.navigation.navigate({
routeName: 'Home',
key: 'Home',
params: { userInfo: 'hello world' },
});
} else {
this.props.navigation.navigate('SignIn');
}
};
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const AppStack = createStackNavigator(
{ Home: HomeScreen, Other: OtherScreen },
{ initialRouteKey: 'Home', initialRouteName: 'Home' }
);
const AuthStack = createStackNavigator({ SignIn: SignInScreen });
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
},
),
);
But i am getting an error as shown in screenshot.
Please suggest a solution.
Also, i want to know how to decide which packages will work with reactnative-cli, expo-managed-cli, expo bare-cli ?
Thanks.

Rematch for Redux: Struggling to see state on different screens

I am new to Rematch for Redux. I am redoing my application using Rematch, but I do not know if I am doing any of this correctly? How/Where do I trigger my reducers and effects (Step 3 in Rematch Docs)? I cannot see my state when I switch between screens. The state seems to be resetting. Could someone please help me? I would greatly appreciate it.
I followed this: https://github.com/rematch/rematch
Here is my code down below:
My application will get bigger, thus the reason why I placed these in different files to build up into the models.js.
store/user.js
const user = {
state: {},
reducers: {
login(payload) { return payload },
email(state, payload) {
return { ...state, payload }
},
password(state, payload) {
return { ...state, payload }
},
username(state, payload) {
return { ...state, payload }
},
fullname(state, payload) {
return { ...state, payload }
},
}
}
export default user
store/index.js
import { init } from '#rematch/core'
import user from './user'
const models = {
user,
}
const store = init({
models,
})
export default store
App.js
import * as React from 'react';
import SwitchNavigator from './navigation/switchNavigator'
import { Provider } from 'react-redux'
import 'redux'
import store from './store/index'
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<SwitchNavigator/>
</Provider>
);
}
}
navigation/switchNavigator
import * as React from 'react';
import TabNavigatorScreen from './tabNavigator'
import AuthNavigatorScreen from './authNavigator'
import { createAppContainer } from 'react-navigation';
import { createSwitchNavigator } from 'react-navigation-switch-transitioner'
const switchNavigator = createSwitchNavigator(
{
Home: {
screen: TabNavigatorScreen
},
Auth: {
screen: AuthNavigatorScreen
}
},
{
initialRouteName: 'Auth',
}
);
export default createAppContainer(switchNavigator);
navigation/authNavigator
import * as React from 'react';
import LoginScreen from '../screens/login'
import SignUpScreen from '../screens/signup'
import MainScreen from '../screens/main'
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
const authNavigator = createStackNavigator(
{
Main: {
screen: MainScreen,
navigationOptions: {
header: null,
}
},
Login: {
screen: LoginScreen,
navigationOptions: {
title: 'Login',
headerTintColor: '#404040',
headerTitleStyle: {
color: '#404040',
},
headerBackTitleStyle: {
color: '#404040',
},
headerBackTitle: null,
}
},
Signup: {
screen: SignUpScreen,
navigationOptions: {
title: 'Sign Up',
headerTintColor: '#404040',
headerTitleStyle: {
color: '#404040',
},
headerBackTitleStyle: {
color: '#404040',
},
headerBackTitle: null,
}
}
},
{
initialRouteName: 'Main',
}
);
export default createAppContainer(authNavigator);
screens/signUp
import * as React from 'react';
import {
TextInput,
Text,
KeyboardAvoidingView,
SafeAreaView,
TouchableOpacity,
Alert,
}
from 'react-native';
import styles from '../styles'
import { connect } from 'react-redux';
import '#expo/vector-icons';
import 'redux';
class Signup extends React.Component {
render() {
const { routeName } = this.props.navigation.state
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView behavior='position'>
<Text style={styles.mainText}>
EMAIL
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.email}
onChangeText={input => this.props.email(input)}
/>
<Text style={styles.mainText}>
PASSWORD
</Text>
<TextInput
style={styles.inputText}
editable={routeName === 'Signup' ? true : false}
value={this.props.user.password}
onChangeText={input => this.props.password(input)}
secureTextEntry={true}
/>
<Text style={styles.mainText}>
USERNAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.username}
onChangeText={input => this.props.username(input)}
/>
<Text style={styles.mainText}>
FULL NAME
</Text>
<TextInput
style={styles.inputText}
value={this.props.user.fullname}
onChangeText={input => this.props.fullName(input)}
/>
<TouchableOpacity
style={styles.buttonLighGray}
onPress={() => Alert.alert('Sign up')}>
<Text style={styles.buttonDarkText}>
Accept & Sign Up
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
const mapState = (state) => ({
user: state.user,
})
const mapDispatch = ({ user: { email, password, username, fullname }}) => ({
email: () => email(),
password: () => password(),
username: () => username(),
fullname: () => fullname(),
})
export default connect(mapState, mapDispatch)(Signup)
The Login screen is using the same state as Sign up screen.
The state will never change because you don't pass any parameters while dispatching an action.
const mapDispatch = dispatch => ({
setEmail: mail => dispatch.user.email(mail)
})
Everytime you called a function before you just invoked the reducer without a parameter.
Regarding your rematch model. Your reducers should not just return ...state & payload. Try to
const user = {
state: {},
reducers: {
email(state, email) {
return { ...state, email }
},
password(state, password) {
return { ...state, password }
},
username(state, username) {
return { ...state, username }
},
fullname(state, fullname) {
return { ...state, fullname }
},
}
}

How to reset in react navigation

I'm building a App with a QRCode Scanner and React Navigation. After navigating from the QRScanner to another screen the QRScanner is still active. I found out, that I have to reset my Navigator with StackActions (right?). I tried it with this in my success screen (which comes after the QRScanner):
const resetAction = StackActions.reset({
index: 3,
actions: [NavigationActions.navigate({ routeName: 'VerificationSuccess' })],
});
this.props.navigation.dispatch(resetAction);
But it doesn't work. Unfortunately, I could find any tutorial...
This is my navigator:
import { createStackNavigator } from 'react-navigation';
import VerificationScreen from './VerificationScreen';
import QRScanner from './QRScanner';
import ChatG from '../ChatG';
import VerificationSuccess from './VerificationSuccess';
export default createStackNavigator(
{
VerificationScreen: {
screen: VerificationScreen,
},
QRScanner: {
screen: QRScanner,
},
VerificationSuccess: {
screen: VerificationSuccess,
},
ChatG: {
screen: ChatG,
}
}
);
Could someone please help me?
You may not be familiar with SwitchNavigator yet. The purpose of SwitchNavigator is to only ever show one screen at a time.
Use switchStackNavigator as below:
const AppStack = AppStackNavigator;
const AuthStack = AuthStackNavigator;
export default createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack
},
{
initialRouteName: "AuthLoading"
}
);
Full working example below,
import React from 'react';
import {
ActivityIndicator,
AsyncStorage,
Button,
StatusBar,
StyleSheet,
View,
} from 'react-native';
import { StackNavigator, SwitchNavigator } from 'react-navigation'; // Version can be specified in package.json
class SignInScreen extends React.Component {
static navigationOptions = {
title: 'Please sign in',
};
render() {
return (
<View style={styles.container}>
<Button title="Sign in!" onPress={this._signInAsync} />
</View>
);
}
_signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('App');
};
}
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome to the app!',
};
render() {
return (
<View style={styles.container}>
<Button title="Show me more of the app" onPress={this._showMoreApp} />
<Button title="Actually, sign me out :)" onPress={this._signOutAsync} />
</View>
);
}
_showMoreApp = () => {
this.props.navigation.navigate('Other');
};
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class OtherScreen extends React.Component {
static navigationOptions = {
title: 'Lots of features here',
};
render() {
return (
<View style={styles.container}>
<Button title="I'm done, sign me out" onPress={this._signOutAsync} />
<StatusBar barStyle="default" />
</View>
);
}
_signOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
}
class AuthLoadingScreen extends React.Component {
constructor() {
super();
this._bootstrapAsync();
}
// Fetch the token from storage then navigate to our appropriate place
_bootstrapAsync = async () => {
const userToken = await AsyncStorage.getItem('userToken');
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away.
this.props.navigation.navigate(userToken ? 'App' : 'Auth');
};
// Render any loading content that you like here
render() {
return (
<View style={styles.container}>
<ActivityIndicator />
<StatusBar barStyle="default" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const AppStack = StackNavigator({ Home: HomeScreen, Other: OtherScreen });
const AuthStack = StackNavigator({ SignIn: SignInScreen });
export default SwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}`enter code here`
);

React Native with Redux : data is loaded, render shows empty

I have a react native app with react-redux , redux-persist and redux-thunk.
in the Component, I'm rendering the data from props, if the data length is less than one, i show an error, no data available.
it's always showing 'no data available' but actually data is in the props. as i check the console logs, ( using redux-logger ) data is available in the props.
if i put forceUpdate() at componentDidMount doesnt even help.
but if i put the forceUpdate() with a timeout it will load the data.
setTimeout(()=>{
this.forceUpdate();
}, 1000);
What could be the problem? Is render happening before data loads from props?
CoursesPage.js
import {bindActionCreators} from "redux";
import {connect} from "react-redux";
import Courses from "./components/Courses";
import {Actions as routes} from "react-native-router-flux";
import * as courseActions from "./courses.actions";
function mapStateToProps(state) {
return {
user: state.auth.user,
users: state.auth.users,
courses: state.courses.courses,
lectures: state.courses.lectures,
courseDetails: routes.courseDetails,
openProfile: routes.profilePage
}
}
function dispatchToProps(dispatch) {
return bindActionCreators({
getCourses: courseActions.getCourses
}, dispatch);
}
export default connect(mapStateToProps, dispatchToProps)(Courses);
Courses.js
import React, {Component, PropTypes} from "react";
import {
ActivityIndicator,
ListView,
StyleSheet,
Text,
View,
Image,
NetInfo,
Alert,
TouchableOpacity,
ScrollView,
Dimensions,
Platform,
RefreshControl
} from 'react-native';
import { Loader, Accordion, I18n, CustomNavBar, CustomAccordion } from "../../common/components";
import styles from "../../common/styles";
let DeviceInfo = require('react-native-device-info');
import Icon from 'react-native-vector-icons/Ionicons';
let { width, height } = Dimensions.get('window');
export default class Courses extends Component {
static propTypes = {
user: PropTypes.string.isRequired,
users: PropTypes.object.isRequired,
courseDetails: PropTypes.func.isRequired,
courses: PropTypes.object.isRequired,
getCourses: PropTypes.func.isRequired,
openProfile: PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.state = {
isLoading: false,
isRefreshing: false
};
this._isMounted = false;
}
componentWillMount(){
this._isMounted = true;
const { users, getCourses } = this.props;
getCourses(users);
}
componentWillUnmount(){
this._isMounted = false;
}
componentWillReceiveProps(){
setTimeout(()=>{
this.forceUpdate();
}, 1000);
}
componentDidMount(){
setTimeout(()=>{
this.forceUpdate();
}, 1000);
setTimeout(()=>{
this.forceUpdate();
}, 2000);
}
async loadData(){
await this.props.getCourses(this.props.users);
setTimeout(()=>{
this.forceUpdate();
}, 1000);
}
selectRow(courseData) {
this.props.courseDetails({
courseData: courseData
});
}
renderData(containerList){
/* rendering .... */
}
render() {
const {user, users, getCourses, courses, openProfile} = this.props;
const data = courses[user];
let containerList = [];
Object.keys(data).forEach((d)=>{
let courseList = [];
Object.keys(data[d].courses).forEach((c)=>{
courseList.push(data[d].courses[c]);
});
containerList.push({
id: data[d].id,
title: data[d].title,
courses: courseList
});
});
return (
<View style={styles.container}>
<View style={{ width: width, height: Platform.OS == "ios" ? 64 : 54}}>
<CustomNavBar
width={width}
height={Platform.OS == "ios" ? 64 : 54}
title={I18n.t("details_page_book_button")}
titleSize={18}
buttonSize={15}
background={"#00a2dd"}
color={"#FFF"}
rightIcon={"ios-person-outline"}
rightIconSize={30}
rightAction={()=> { openProfile(); }}
/>
</View>
<View style={{ height: Platform.OS == "ios" ? height - 114 : height - 130 }}>
{!this.state.isLoading ?
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={this.loadData.bind(this)}
tintColor="#00a2dd"
title=""
titleColor="#00a2dd"
colors={['#00a2dd', '#00a2dd', '#00a2dd']}
progressBackgroundColor="#FFFFFF"
/>
}
>
{this.renderData(containerList)}
</ScrollView>
:<ActivityIndicator
animating={true}
style={{ paddingTop: Platform.OS == "ios" ? (height - 114)/2 : (height - 130)/2 }}
color={'#00a2dd'}
size={'small'}
/>}
</View>
</View>
);
}
}
I think you dont change state so it is seen same data.So I suggest you should change code like following.Also you should immutable js to change state.
courseActions:
export function getCoursesRequest () {
return {
type: "GET_COURSES_REQUEST"
}
}
export function getCoursesSuccess (json) {
return {
type: "GET_COURSES_SUCCESS",
payload: json
}
}
export function getCoursesFailure (json) {
return {
type: "GET_COURSES_FAILURE",
payload: json
}
}
export function getCourses (sessionToken) {
return dispatch => {
dispatch(getCoursesRequest())
// store or get a sessionToken
return appAuthToken.getSessionToken(sessionToken)
.then((token) => {
return BackendFactory(token).getCourses()
})
.then((json) => {
dispatch(getCoursesSuccess(json))
})
.catch((error) => {
dispatch(getCoursesFailure(error))
})
}
}
coursesInitialState
const {Record} = require("immutable");
var InitialState = Record({
courses: {}
});
export default InitialState;
reducer:
const InitialState = require("./authInitialState").default;
const initialState = new InitialState();
export const courseReducer = (state = initialState, action) => {
if (!(state instanceof InitialState)) return initialState.mergeDeep(state);
switch (action.type) {
case "GET_COURSES_SUCCESS":
const {value} = action.payload;
let nextState = state.setIn(["courses"], value;
return nextState;
case "GET_COURSES_FAILURE":
}
}

Resources