Description:
I’m experiencing an issue with conditional rendering in my React Native application using Expo 52 and expo-router ~4.0.5. Specifically, I expect my app to show a DrawerLayout when the user variable has a value (indicating the user is logged in) and a Stack with login/registration screens when user is null or undefined. However, even when user is false or null, the app incorrectly renders the DrawerLayout.
Environment:
React Native: 0.76.2
Expo SDK version: 52.0.7
expo-router version: ~4.0.5
Project Structure:
App/
(auth)/
_layout.tsx
login.tsx
register.tsx
(drawer)/
_layout.tsx
index.tsx
user_profile.tsx
_layout.tsx <- Conditional rendering logic is here
Code for App/_layout.tsx:
export default function Layout() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [user, setUser] = useState(null);
const [isInitialized, setIsInitialized] = useState(false);
const tamaguiConfig = createTamagui(config);
const [loaded] = useFonts({
Inter: require('@tamagui/font-inter/otf/Inter-Medium.otf'),
InterBold: require('@tamagui/font-inter/otf/Inter-Bold.otf'),
});
useEffect(() => {
async function initializeApp() {
try {
console.log("Iniciando loadUser...");
const userData = await loadUser();
console.log("userData recibido:", userData);
setUser(userData);
} catch (e) {
console.error("Error en loadUser:", e);
} finally {
setIsInitialized(true);
}
}
initializeApp();
}, []);
if (!isInitialized || !loaded) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<TamaguiProvider config={tamaguiConfig}>
<Theme name="light">
<AuthContext.Provider value={{ user, setUser }}>
{isInitialized && (
user ? (
// Even when `user` is falsy, <DrawerLayout /> is rendered.
<DrawerLayout />
) : (
<Stack>
<Stack.Screen
name="(auth)"
options={{ headerShown: false }}
/>
</Stack>
)
)}
</AuthContext.Provider>
</Theme>
</TamaguiProvider>
);
}
App/(drawer)/_layout.tsx
const DrawerLayout = () => {
const [newRecipeGenerated, setNewRecipeGenerated] = useState(false);
return (
<NewRecipeGenerationContext.Provider value={{ newRecipeGenerated, setNewRecipeGenerated }}>
<Drawer>
<Drawer.Screen name="index" options={{ title: "Home" }} />
<Drawer.Screen name="recipeGeneration" options={{ title: "GeneraciĆ³n Recetas" }} />
<Drawer.Screen name="userRecipes" options={{ title: "Mis Recetas" }} />
</Drawer>
</NewRecipeGenerationContext.Provider>
);
}
App/(auth)/_layout.tsx
export default function AuthLayout() {
return (
<Stack screenOptions={{
headerShown: false
}}>
<Stack.Screen
name="login"
options={{
title: 'Login'
}}
/>
<Stack.Screen
name="register"
options={{
title: 'Register'
}}
/>
</Stack>
);
}
AuthContext:
import { createContext } from "react";
const AuthContext = createContext({
user: null,
setUser: () => {},
});
export default AuthContext;