Search code examples
javascriptreactjsreact-nativereduxredux-toolkit

Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider> in React native Expo App


I am getting this error while trying to run my React-Native app. I am trying to make a React-Native app which will have a BottomNavBar and drawer navigation. I am using Redux-Toolkit for state management. I have followed the documentation and I get this error.

Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>

This error is located at:
    in App (at withDevTools.js:18)
    in withDevTools(App) (at renderApplication.js:57)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:127)
    in RCTView (at View.js:116)
    in View (at AppContainer.js:155)
    in AppContainer (at renderApplication.js:50)
    in main(RootComponent) (at renderApplication.js:67), js engine: hermes

App.js

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Provider, useDispatch, useSelector } from 'react-redux'; // Import Provider
import store from './store/store'; // Assuming your store is here
import { logout } from './store/authSlice'; // Assuming your logout action is here
import * as SecureStore from 'expo-secure-store';
import { Ionicons } from '@expo/vector-icons';

// Import your screen components (replace with your actual screens)
import HomeScreen from './screens/HomeScreen';
import SettingsScreen from './screens/SettingsScreen';
import ProfileScreen from './screens/ProfileScreen';
import FaqScreen from './screens/FaqScreen';
import LoginScreen from './screens/LoginScreen';
import LogoutScreen from './screens/LogoutScreen';
// ... (add other screens as needed)

const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();

const HomeIcon = ({ size, color }) => <Ionicons name="home-outline" size={size} color={color} />;
const ProfileIcon = ({ size, color }) => <Ionicons name="person-outline" size={size} color={color} />;
const SettingsIcon = ({ size, color }) => <Ionicons name="settings-outline" size={size} color={color} />;
const LoginIcon = ({ size, color }) => <Ionicons name="log-in-outline" size={size} color={color} />;

function MyTabs({ isLoggedIn }) {
  return (
    <Tab.Navigator screenOptions={{headerShown: false}} initialRouteName="Home">
      <Tab.Screen
        name="Home"
        component={HomeScreen}
        options={{
          tabBarIcon: ({ color, size }) => <HomeIcon size={size} color={color} />,
        }}
      />
      <Tab.Screen
        name="Settings"
        component={SettingsScreen}
        options={{
          tabBarIcon: ({ color, size }) => <SettingsIcon size={size} color={color} />,
        }}
      />
      {isLoggedIn ? (
        <Tab.Screen
          name="Profile"
          component={ProfileScreen}
          options={{
            tabBarIcon: ({ color, size }) => <ProfileIcon size={size} color={color} />,
          }}
        />
      ) : (
        <Tab.Screen
          name="Login"
          component={LoginScreen}
          options={{
            tabBarIcon: ({ color, size }) => <LoginIcon size={size} color={color} />,
          }}
        />
      )}
      
    </Tab.Navigator>
  );
}

function App() {
    const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
  return (
    <Provider store={store}>
      <NavigationContainer initialRouteName="Home">
        <Drawer.Navigator>
          <Drawer.Screen name="Shop" component={MyTabs} />
          <Drawer.Screen name="FAQ" component={FaqScreen} />
          {isLoggedIn ? <Drawer.Screen name="Logout" component={LogoutScreen} /> : null}
          {/* Add other drawer screens if needed */}
        </Drawer.Navigator>
      </NavigationContainer>
    </Provider>
  );
}

export default App;

Solution

  • The App component is rendering the Redux Provider and so cannot itself access any Redux context because none is provided to it from higher up the ReactTree. It can't use the useSelector hook.

    Update the code such that App is wrapped by the Provider component so it can access the provided Redux context.

    Example:

    function App() {
      const isLoggedIn = useSelector((state) => state.auth.isLoggedIn);
    
      return (
        <NavigationContainer initialRouteName="Home">
          <Drawer.Navigator>
            <Drawer.Screen name="Shop" component={MyTabs} />
            <Drawer.Screen name="FAQ" component={FaqScreen} />
            {isLoggedIn ? <Drawer.Screen name="Logout" component={LogoutScreen} /> : null}
            {/* Add other drawer screens if needed */}
          </Drawer.Navigator>
        </NavigationContainer>
      );
    }
    
    const AppProvider = () => (
      <Provider store={store}>
        <App />
      </Provider>
    );
    
    export default AppProvider;