marklawlor / nativewind

React Native utility-first universal design system - powered by Tailwind CSS
https://nativewind.dev
MIT License
4.3k stars 233 forks source link

V4 unclear warnings: Making a component inheritable should only happen during the initial render #873

Open dannyhw opened 1 month ago

dannyhw commented 1 month ago

Describe the bug

I keep running into this but its not clear to me what this means, it would be good to have documentation or examples of wrong/correct usage

Making a component inheritable should only happen during the initial render otherwise it will remount the component.

To prevent this warning avoid dynamically adding CSS variables or 'container' styles to components after the initial render, or ensure it has a default style that sets either a CSS variable, "container: none" or "container-type: none".

If add/removing sibling components cause this warning, add a unique "key" prop so React can correctly track this component.

To Reproduce Steps to reproduce the behavior:

  1. seems to happen whenever I pass a component as a prop

For example with react hook form

<Controller
          name="email"
          control={control}
          render={({ field: { onChange, onBlur, value }, fieldState }) => (
            <View className="mb-2">
              <TextInput
                accessibilityHint="Enter your email"
                accessibilityLabel="Email"
                autoCapitalize="none"
                autoComplete="email"
                className="items-center justify-center rounded-lg border border-gray-300 bg-white p-4 outline-0"
                keyboardType="email-address"
                onChangeText={onChange}
                onSubmitEditing={() => passwordRef.current?.focus()}
                placeholder="Email"
                ref={emailRef}
                returnKeyType="next"
                onBlur={onBlur}
                underlineColorAndroid="transparent"
                value={value}
              />
              <View className="min-h-4">
                {fieldState.error && (
                  <Text className="text-xs text-red-500">{fieldState.error.message}</Text>
                )}
              </View>
            </View>
          )}
        />

I get the warning from this component

The previous warning was caused by a component with these props: {"accessibilityHint":"Enter your email","accessibilityLabel":"Email","autoCapitalize":"none","autoComplete":"email","className":"items-center justify-center rounded-lg border border-gray-300 bg-white p-4 outline-0","keyboardType":"email-address","placeholder":"Email","returnKeyType":"next","underlineColorAndroid":"transparent","value":"asd@a.com"}

What is incorrect in this case? this kind of pattern is relatively common so I'm clear on what the issue is.

Expected behavior

Either a clearer explanation or some documentation on how to avoid this behaviour.

Expo Snack If applicable, add a link to an Expo snack demonstrating the issue. There are multiple example snacks available at nativewind.dev.

Screenshots If applicable, add screenshots to help explain your problem.

Additional context Add any other context about the problem here.

dannyhw commented 1 month ago

seem to get this on many components and I don't get it 😅

this one too

   <TouchableOpacity className="rounded-md bg-slate-700 px-8 py-4" onPress={onSubmit}>
          {isSubmitting ? (
            <ActivityIndicator size="small" className="h-6" />
          ) : (
            <Text className="text-center text-base text-white">Sign In</Text>
          )}
        </TouchableOpacity>
rmarquois commented 1 month ago

In my case, it was due to a dynamic className on a Pressable which has a shadow depending on if it's active or not. I had to add an initial shadow to my Pressable component and set it to "shadow-none" to avoid this warning.

In your case you don't have a dynamic className so I don't get it too :(

the-simian commented 1 month ago

I've noticed this being thrown on Pressable components. I've been moving the classes to a View beneath the Pressable, which seems to help some. I'm getting this throughout my project on first load, and I've not yet zeroed in on the root cause. These logs are extremely verbose atm, and totally flood the console. The most useful part is The previous warning was caused by a component with these props and you'll see some CSS classes that are (probably) unique enough to track down the problem.

vktrl commented 4 weeks ago

Getting the same and the root cause is very hard to track down. Right now it seems that it has something to do with the bundler and react-native-css-interop module. I can't extract the code from my repo for reproduction, but maybe something in the following can provide hints:

  1. I have a Pressable with dynamic classes. I'm using code from react-native-reusables which has utilizes a context for setting text colors and other stuff. Relevant code here.
  2. I start expo go server and open the Expo Go app on iOS. Everything runs perfectly, hot reloads are fine, full reloads are fine.
  3. I open the web app in the browser and iOS app crashes immediately. Getting this in the console:
    
    WARN  CssInterop upgrade warning.

Making a component inheritable should only happen during the initial render otherwise it will remount the component.

To prevent this warning avoid dynamically adding CSS variables or 'container' styles to components after the initial render, or ensure it has a default style that sets either a CSS variable, "container: none" or "container-type: none".

If add/removing sibling components cause this warning, add a unique "key" prop so React can correctly track this component. at CssInterop.Text (http://expo.local.mydomain.com/services/frontend/index.ts.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.asyncRoutes=true&transform.routerRoot=src%2Fapp:11464:45)

// truncated

WARN The previous warning was caused by a component with these props: {"className":"web:select-text text-card-foreground text-xs font-semibold uppercase color-white","children":"ct"} at CssInterop.Text (http://expo.local.mydomain.com/services/frontend/index.ts.bundle//&platform=ios&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.bytecode=true&transform.asyncRoutes=true&transform.routerRoot=src%2Fapp:11464:45)

// truncated

ERROR Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

This error is located at: in CssInterop.Text (created by Text)


When I reload the Expo Go app on iOS after the crash I see that styles with the `web:` variant are being applied in the iOS build. When I tap on a Pressable, the Expo Go app crashes. This will happen until I stop and restart the expo server with a fresh bundle. Note that the printed warning also includes web classes in the `className` prop.

Not sure if the issue is with Nativewind platform-specific styling being broken or it's an issue with the bundler. There's a [potentially related issue here](https://github.com/marklawlor/nativewind/issues/645).

tl;dr - bundling for web breaks the running iOS build by adding web styles to it.