I am trying to use the user state to determine if my app shows the authentication group or not, but now I understand that the setup that I have cannot work because the the root layout component cannot access the state.
How can get accomplish my goal?
import {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import { Drawer } from "expo-router/drawer";
import * as SplashScreen from "expo-splash-screen";
import { StatusBar } from "expo-status-bar";
import { useEffect } from "react";
import "react-native-reanimated";
import { useColorScheme } from "@/hooks/useColorScheme";
import { selectCurrentUser } from "@/store/auth/authSlice";
import { useSelector } from "react-redux";
import "react-native-gesture-handler";
import { Provider } from "react-redux";
import store from "../store/store";
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
const currentUser = useSelector(selectCurrentUser);
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<Provider store={store}>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
{currentUser ? (
<Drawer>
<Drawer.Screen name="(tabs)" options={{ headerShown: false }} />
<Drawer.Screen name="+not-found" />
</Drawer>
) : (
<Stack>
<Stack.Screen
name="(authentication)"
options={{ headerShown: false }}
/>
</Stack>
)}
<StatusBar style="auto" />
</ThemeProvider>
</Provider>
);
}
I tried using select current user but I got this error: could not find react-redux context value
The RootLayout
component is the component rendering the Redux Provider
component that provides the Redux context, so it itself cannot use the useSelector
hook. Push the Provider
higher up the ReactTree, or push the currentUser ? ....
logic lower down the ReactTree.
Examples:
Push Provider
up the ReactTree
import { Provider } from "react-redux";
import store from "../store/store";
...
<Provider store={store}>
<RootLayout />
</Provider>
export default function RootLayout() {
const currentUser = useSelector(selectCurrentUser);
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
{currentUser ? (
<Drawer>
<Drawer.Screen name="(tabs)" options={{ headerShown: false }} />
<Drawer.Screen name=" + not-found" />
</Drawer>
) : (
<Stack>
<Stack.Screen
name="(authentication)"
options={{ headerShown: false }}
/>
</Stack>
)}
<StatusBar style="auto" />
</ThemeProvider>
);
}
Push the consumer down the ReactTree
const App = () => {
const currentUser = useSelector(selectCurrentUser);
return currentUser
? (
<Drawer>
<Drawer.Screen name="(tabs)" options={{ headerShown: false }} />
<Drawer.Screen name=" + not-found" />
</Drawer>
) : (
<Stack>
<Stack.Screen
name="(authentication)"
options={{ headerShown: false }}
/>
</Stack>
);
};
export default function RootLayout() {
const colorScheme = useColorScheme();
const [loaded] = useFonts({
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
});
useEffect(() => {
if (loaded) {
SplashScreen.hideAsync();
}
}, [loaded]);
if (!loaded) {
return null;
}
return (
<Provider store={store}>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<App />
<StatusBar style="auto" />
</ThemeProvider>
</Provider>
);
}