I am fairly new to react-native and have been hitting the following error while trying to set up my appNavigation along with redux.
TypeError: (0, _reactNavigation.addNavigationHelpers) is not a function. (In '(0, _reactNavigation.addNavigationHelpers)({dispatch:dispatch, state: nav})' (0, _reactNavigation.addNavigationHelpers)' is undefined.
Code -->
App.js -
import React from 'react';
import store from './src/store';
import { Provider } from 'react-redux';
import 'react-native-gesture-handler';
import AppNavigation from './src/components/AppNavigator';
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AppNavigation />
</Provider>
);
}
}
AppNavigator.js -
import React from 'react';
import TodoApp from '../TodoApp';
import TodoDetails from '../components/TodoDetails';
import { connect } from 'react-redux';
import { addNavigationHelpers } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
export const AppNavigator = createStackNavigator(
{
todoDetails: TodoDetails,
home: TodoApp,
},
{
initialRouteName: 'todoDetails',
},
);
const AppNavigation = ({ dispatch, nav }) => (
<AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
);
const mapStateToProps = state => ({
nav :state.nav,
});
export default connect(mapStateToProps)(AppNavigation);
EDIT -
I did follow the steps given at https://stackoverflow.com/questions/50246457/react-native-reactnavigation-addnavigationhelpers-in-not-a-function
But unfortunately, that gives an error saying
TypeError: undefined is not an object (evaluating 'state.routes')
The error is located at:
in Navigator (at AppNavigator.js:20)
in AppNavigation (created by ConnectFunction)
in ConnectFunction (at App.js:19)......
addNavigationHelpers has been removed from react-navigation's default exports,
you need to directly add to the navigation props as
<AppNavigator navigation={{
dispatch: this.props.dispatch,
state: this.props.nav,
addListener,
}} />
A great answer by pritish , hope it help.s
Related
I want to redirect my current app screen to login screen if the user is not authenticated. So I created a global component RedirectorToLogin and use this component in my App.js . But I'm getting this error Couldn't find a navigation object. Is your component inside a screen in a navigator ? because I'm using useNavigation inside RedirectorToLogin.
What is the reason for this error to be occured ?
My RedirectorToLogin.js
import React, { useContext, useEffect } from 'react'
import { useNavigation } from '#react-navigation/native'
import AuthGlobal from '../Context/store/AuthGlobal'
const RedirectorToLogin = (props) => {
const context = useContext(AuthGlobal)
const navigation = useNavigation()
useEffect(() => {
if (!context.stateUser.isAuthenticated) {
navigation.navigate('Login')
}
return () => {}
}, [context.stateUser.isAuthenticated])
return <></>
}
export default RedirectorToLogin
My App.js
import { StatusBar } from 'expo-status-bar'
import React from 'react'
import { LogBox } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import Toast from 'react-native-toast-message'
import ErrorBoundary from 'react-native-error-boundary'
// Redux
import { Provider } from 'react-redux'
import store from './Redux/store'
// Context API
import Auth from './Context/store/Auth'
// Navigatiors
import Main from './Navigators/Main'
// Screens
import Header from './Shared/Header'
import MyAppState from './Global/MyAppState'
import Network from './Global/Network'
import RedirectorToLogin from './Global/RedirectorToLogin'
const errorHandler = (error, stackTrace) => {
/* Log the error to an error reporting service */
console.log('**** error log form error handler ****')
console.log(error)
console.log(stackTrace)
console.log('**** **** ****')
}
LogBox.ignoreAllLogs(true)
export default function App() {
return (
<ErrorBoundary onError={errorHandler}>
<Auth>
<Provider store={store}>
<NavigationContainer>
<Header />
<Main />
<MyAppState />
<Network />
<RedirectorToLogin />
<Toast ref={(ref) => Toast.setRef(ref)} />
</NavigationContainer>
</Provider>
</Auth>
</ErrorBoundary>
)
}
I referred to this article and updated my Main.js to show only login navigator when user is not authenticated. So I can get rid of having RedirectorToLogin
I have created customized sidebar and have 5 to 6 screens. I am using NativeBase and want to open Sidebar with DrawerNavigator option but when I applied following code it was getting issue.
Drawer Navigator code
import React, { Component } from "react";
import WelcomeScreen from './screens/WelcomeScreen';
import ContactScreen from './screens/ContactScreen';
import DepartmentScreen from './screens/DepartmentScreen';
import EmailServiceScreen from './screens/EmailServiceScreen';
import MoreScreen from './screens/MoreScreen';
import SideBar from "./SideBar.js";
import { DrawerNavigator } from "react-navigation";
const SidebarNavigator = DrawerNavigator(
{
Home: { screen: WelcomeScreen },
Contact: { screen: ContactScreen },
Department: { screen: DepartmentScreen },
EmailService: { screen: EmailServiceScreen },
More: { screen: MoreScreen }
},
{
contentComponent: props => <SideBar {...props} />
}
);
export default SidebarNavigator;
Calling them in APP.Js as propos. See following code from APP.JS
import SidebarNavigator from './src/SidebarNavigator';
class App extends Component {
render() {
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
return (
<Provider store={createStore(reducers)}>
<Root>
<Router /> // It's a stack navigator which is working fine
<SidebarNavigator />
</Root>
</Provider>
);
}
}
console.disableYellowBox = true;
export default App;
The error here is that you are using DrawerNavigation instead of createDrawerNavigator.
Just do those changes and you should be good
import { createDrawerNavigator } from "react-navigation";
...
const SidebarNavigator = createDrawerNavigator( ... )
Source: https://reactnavigation.org/docs/en/drawer-navigator.html
You can try this code
You can use createDrawerNavigator and createAppContainer
import { createDrawerNavigator, createAppContainer } from "react-navigation";
...
const SidebarNavigator = createDrawerNavigator( ... )
const AppContainer = createAppContainer(SidebarNavigator);
// Now AppContainer is the main component for React to render
export default AppContainer;
I am having trouble connecting the tab navigator (from React-Navigation v3) to the redux provider.
So this is how my react-navigation and redux is configured:
app/
/react-redux provider
/app-container (this is the AppContainer of the main SwitchNavigator)
/welcome-screen
/login-screen
/register-screen
/home-navigator (this is the TabNavigator that is inside the SwitchNavigator)
Home navigator holds the screens to which user is directed to when he logs-in. In the first 3 screends (welcome, login and register) I can access the functions that are "connected" from redux to the screen through standard mapDispatchToProps.
This is the app component:
/**
* Entry point for the app
*/
import React, { Component } from "react";
// redux
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import reduxThunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import main_app_reducer from "./modules/core/reducers/main_app_reducer";
// create redux store
const create_store = composeWithDevTools(applyMiddleware(reduxThunk))(createStore);
export const store = create_store(main_app_reducer);
// navigation
import AppContainer from "./modules/core/components/AppNavigator";
import { configure_axios } from "./helpers/axios_config";
configure_axios();
class App extends Component {
render() {
return (
<Provider store={store}>
<AppContainer />
</Provider>
);
}
}
export default App;
And then, from there we go to AppContainer:
/**
* this components ensures app navigation so that user can jump from one screen to another
*/
// navigation
import { createSwitchNavigator, createAppContainer } from "react-navigation";
// screens
import WelcomeScreen from "../screens/WelcomeScreen";
import LoginScreen from "../../auth/screens/LoginScreen";
import RegisterScreen from "../../auth/screens/RegisterScreen";
import HomeNavigator from "./HomeNavigator";
const AppSwitchNavigator = createSwitchNavigator({
// for users that are not logged in yet
Welcome: { screen: WelcomeScreen },
Login: { screen: LoginScreen },
Register: { screen: RegisterScreen },
// for logged in users
HomeNavigator: { screen: HomeNavigator },
});
const AppContainer = createAppContainer(AppSwitchNavigator);
export default AppContainer;
All of the code above works perfectly with no errors, the problem occurs inside the HomeNavigator component that you see below.
This is the HomeNavigator component:
import { createBottomTabNavigator } from "react-navigation";
import { HomeScreen } from "../screens/HomeScreen";
import { DashboardScreen } from "../screens/DashboardScreen";
const HomeNavigator = createBottomTabNavigator(
{
Home: { screen: HomeScreen },
Dashboard: { screen: DashboardScreen },
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
headerTitle: routeName,
};
},
},
);
export default HomeNavigator;
NONE of the screens inside the HomeNavigator are connected to Redux altough they are defined THE SAME WAY as the screens inside AppContainer file. For comparison let's see Login screen from AppContainer and Home screen from HomeNavigator:
LoginScreen:
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { get_user_servers } from "../actions/core_actions";
export class LoginScreen extends Component {
componentDidMount() {
this.props.get_user_servers(); // this function works absolutely fine
}
render() {
return (
<View>
<Text> LoginScreen </Text>
</View>
);
}
}
const mapStateToProps = (state) => ({});
const mapDispatchToProps = { get_user_servers };
export default connect(
mapStateToProps,
mapDispatchToProps,
)(LoginScreen);
HomeScreen:
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { get_user_servers } from "../actions/core_actions";
export class HomeScreen extends Component {
componentDidMount() {
this.props.get_user_servers();
// the same function as in LoginScreen but here the function does not work
// I'm getting an error = TypeError: this.props.get_user_servers is not a function (see picture below)
}
render() {
return (
<View>
<Text> HomeScreen </Text>
</View>
);
}
}
const mapStateToProps = (state) => ({});
const mapDispatchToProps = { get_user_servers };
export default connect(
mapStateToProps,
mapDispatchToProps,
)(HomeScreen);
That function (get_user_servers) is defined properly and it works fine in LoginScreen.
thanks everyone who took their time to help me, in the end it was my mistake that I overlooked. If you check out the third code-block from this question you can see that I import my components like this:
import { HomeScreen } from "../screens/HomeScreen";
import { DashboardScreen } from "../screens/DashboardScreen";
Which is wrong, I changed that to:
import HomeScreen from "../screens/HomeScreen";
import DashboardScreen from "../screens/DashboardScreen";
And now everything works fine, thanks again :)
Assuming it's the same function you're importing, please could you try to check your import of get_user_servers function from both screen : LoginScreen and HomeScreen. According to your code it look like LoginScreen ("../../auth/screens/LoginScreen") and HomeScreen ("../screens/HomeScreen") are not in the same path.
As asked above, could check the path of the files, or post it so we can help. Also could you open the remote debugger, and inside the componentWillMount you can put:
console.log(this.props)
to check if the HomeScreen is geting the function inside props.
I'm using react-navigation and redux for navigation between screens I'm getting an error instead.
Invariant Violation: createReduxBoundAddListener is deprecated in
react-navigation-redux-helpers#2.0.0! Please use reduxifyNavigator
I don't know how to fix it please help me out.
App.js
import React from 'react';
import { Provider } from "react-redux";
import store from "./src/redux/store"
import { createReduxBoundAddListener } from "react- navigation-redux-helpers";
import AppWithNavigationState from "./src/navigators/AppNavigator";
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
//Here Im getting an error regarding creacteReduxBoundAddListener
<AppWithNavigationState listener{createReduxBoundAddListener("root")}/>
</Provider>
);
}
}
AppNavigator.js file
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import {connect} from "react-redux";
import {PropTypes} from 'prop-types';
import {addNavigationHelpers,createStackNavigator } from "react-navigation";
import LoggedOut from "../screens/LoggedOut";
import LogIn from "../screens/Login";
import ForgotPassword from "../screens/ForgotPassword";
// created screens using createStackNavigator
export const AppNavigator = createStackNavigator({
LoggedOut:{screen:LoggedOut},
LogIn:{screen:LogIn},
ForgotPassword:{screen:ForgotPassword},
});
const AppWithNavigationState = ({ dispatch,nav,listener}) =>{
<AppNavigator navigation=
{addNavigationHelpers({dispatch,state:nav,addListener:listener})}/>
};
AppWithNavigationState.propTypes = {
dispatch:PropTypes.func.isRequired,
nav:PropTypes.object.isRequired
};
const mapStateToProps = state =>({
nav:state.nav,
});
export default connect(mapStateToProps)(AppWithNavigationState);
navigation.js
import {AppNavigator} from "../../navigators/AppNavigator";
const firstAction =
AppNavigator.router.getActionForPathAndParams("LoggedOut"); //decide which
//screen will
//load first
const initialNavState = AppNavigator.router.getStateForAction(firstAction);
export const nav = (state=initialNavState, action)=>{
let nextState = AppNavigator.router.getStateForAction(action,state);
return nextState || state;
}
You can check this repo https://github.com/JaiDeves/AirBnB-React, I've updated the code with the newer version of react-navigation.
I am trying to use switch navigator with redux. following is my code.
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
import LoginScreen from '../screens/LoginScreen';
import EmployeeListScreen from '../screens/EmployeeListScreen';
import DetailsView from '../screens/EmployeeDetailViewScreen';
import EmployeeForm from '../screens/EmployeeForm';
import AuthLoadingScreen from "../screens/AuthLoadingScreen.js";
import {connect } from "react-redux";
import { AppNavigator } from "../navigations/AppNavigator.js";
const AppStack = createStackNavigator({
List:{screen:EmployeeListScreen},
Detail:{screen:DetailsView},
Form:{screen:EmployeeForm}
});
const AuthStack = createStackNavigator({ Login: LoginScreen });
export const AuthNavigator = createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppNavigator,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I'm importing this component is my App.js file and using it as follows to connect with redux store but it is giving me error like, React is not defined and error is located at connect(AuthWithNavigationState)
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthWithNavigationState from './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthWithNavigationState/>
</Provider>
);
}
}
I've tried to follow instruction from below link but still I am getting the same error.
how can i integrate redux store to react native?
Can anyone tell me what is wrong with my code?
after too much trying, I figure out that, The switch navigator don't need to be connect to the store, so below step was incorrect.
const AuthWithNavigationState = ({ dispatch, nav }) => (
<AuthNavigator />
);
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(AuthWithNavigationState);
I simply exported AuthNavigator and imported in App.js and this worked for me.
import React from 'react';
import { Provider } from 'react-redux';
import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import AppReducer from './src/reducers/AppReducer';
import AuthNavigatorfrom './src/navigations/AuthNavigator.js';
const store = createStore(AppReducer,applyMiddleware(thunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<AuthNavigator/>
</Provider>
);
}
}