nativewind icon indicating copy to clipboard operation
nativewind copied to clipboard

Bug: className with conditional expressions on Pressable breaks React Navigation context

Open shenxiuqiang opened this issue 5 months ago • 4 comments

Body:

Describe the bug

When a Pressable or TouchableOpacity component is rendered within a React Navigation NavigationContainer, applying a conditional className via a template literal causes the app to crash with a "Couldn't find a navigation context" error.

This suggests that NativeWind's runtime processing of dynamic class names interferes with how React Context is passed down the component tree, specifically breaking the context provided by React Navigation. The issue does not occur if the className is a static string.

reproduction

https://stackblitz.com/edit/nativewind-test-veykuvuh?file=App.tsx,global.css

To Reproduce

  1. Set up a React Native project using nativewind@^4.0.0 and @react-navigation/native@^7.0.0.
  2. Wrap the application's root component in a <NavigationContainer>.
  3. In any screen component rendered by the navigator, create a Pressable component whose className is determined by a state variable within a template literal.

Here is a minimal reproducible example:

import React, { useState } from 'react';
import { View, Text, Pressable, SafeAreaView } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider } from 'react-native-safe-area-context';

const Stack = createNativeStackNavigator();

// This component will cause the crash
const MyFailingComponent = () => {
  const [isActive, setIsActive] = useState(false);

  return (
    <Pressable
      onPress={() => setIsActive(!isActive)}
      // The dynamic className is the source of the problem
      className={`p-4 rounded-lg ${isActive ? 'bg-blue-500' : 'bg-gray-500'}`}
    >
      <Text className="font-bold text-white">Toggle Me</Text>
    </Pressable>
  );
};

const HomeScreen = () => {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ marginBottom: 20 }}>This screen will crash</Text>
      <MyFailingComponent />
    </View>
  );
};

const App = () => {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="Home" component={HomeScreen} />
        </Stack.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
};

export default App;

Expected behavior

The application should render without crashing. The Pressable component should correctly toggle its styles based on its state, and the React Navigation context should remain intact and available to all child components.

Screenshots

The app crashes with the standard React Native RedBox error: "Render Error: Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?"

(You can drag-and-drop your screenshot here)

Environment:

  • React Native: 0.80.0
  • React: 19.1.0
  • NativeWind: 4.1.23
  • @react-navigation/native: 7.1.14
  • OS: macOS
  • babel.config.js:
    module.exports = {
      presets: ['module:@react-native/babel-preset'],
      plugins: [
        // ... other plugins
        'nativewind/babel',
      ],
    };
    

Additional context and Workaround

We went through extensive debugging, and the only successful workaround is to completely remove the className prop and use StyleSheet.create instead.

This confirms the issue is with NativeWind's processing.

Workaround Code (This works):

import React, { useState } from 'react';
import { View, Text, Pressable, StyleSheet } from 'react-native';

const MyWorkingComponent = () => {
  const [isActive, setIsActive] = useState(false);

  return (
    <Pressable
      onPress={() => setIsActive(!isActive)}
      style={[
        styles.base,
        isActive ? styles.activeButton : styles.inactiveButton,
      ]}
    >
      <Text style={styles.text}>Toggle Me</Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  base: {
    padding: 16,
    borderRadius: 8,
  },
  activeButton: {
    backgroundColor: '#3b82f6', // bg-blue-500
  },
  inactiveButton: {
    backgroundColor: '#6b7280', // bg-gray-500
  },
  text: {
    fontWeight: 'bold',
    color: 'white',
  },
});

// ... The rest of the App code remains the same, just swap MyFailingComponent for MyWorkingComponent

This workaround strongly suggests that the Babel transform or runtime logic for NativeWind is altering the component in a way that makes it incompatible with React's Context API as used by React Navigation.

shenxiuqiang avatar Jun 30 '25 16:06 shenxiuqiang

👋 Hi, thanks for opening this issue! However, it seems that you did not include a reproduction link.

Please update your issue with one of the following:

Issues without reproductions will not be reviewed and are automatically closed. You can refer to our contribution guide for more information.

If you have additional details, feel free to re-open the issue after providing a valid reproduction link.

If you have a usage question, please use the Discord or GitHub Discussions instead.

github-actions[bot] avatar Jun 30 '25 16:06 github-actions[bot]

Hi, here is the reproduction link as requested: https://stackblitz.com/edit/nativewind-test-veykuvuh?file=App.tsx,global.css

shenxiuqiang avatar Jun 30 '25 17:06 shenxiuqiang

Hi, here is the reproduction link as requested: https://stackblitz.com/edit/nativewind-test-veykuvuh?file=App.tsx,global.css

shenxiuqiang avatar Jul 02 '25 11:07 shenxiuqiang

I'll be reproducing this issue with npx rn-new@latest (Nativewind v4.1 + Expo SDK 54) whereas your project uses SDK 51. It would be helpful if you provide said repro prior to me getting to it.

danstepanov avatar Oct 15 '25 08:10 danstepanov

Was this resolved? Still facing this...

vehbiu avatar Dec 09 '25 01:12 vehbiu

Any update? having the same issue, conditional classNames either as a string or using tva causes this bug... No workarounds found

LarsDanau avatar Dec 16 '25 16:12 LarsDanau