nativewind icon indicating copy to clipboard operation
nativewind copied to clipboard

V4: switching the color scheme becomes very laggy

Open DeluxeOwl opened this issue 2 years ago • 4 comments

Describe the bug Switching from light to dark and viceversa becomes very laggy after a few attempts. The code is a basic example derived from the one shown in https://www.nativewind.dev/v4/guides/themes#switching-themes

To Reproduce Steps to reproduce the behavior:

  1. Go to any screen that has the theme configured like in the above example
  2. Switch between light and dark a few times
  3. It becomes very laggy after a few switches

Expected behavior Not to become laggy

Screenshots

https://github.com/marklawlor/nativewind/assets/54327698/e6d50404-5485-484b-8284-bc6e177785de

Additional context I'm having a theme layout:

import { useColorScheme, vars } from "nativewind";
import React from "react"; // Make sure to import React
import { View } from "react-native";
import colors from "tailwindcss/colors";

type ThemeLayoutProps = {
	children?: React.ReactNode;
};

type RGBTailwindVar = `${number} ${number} ${number}`;

function hexToRgbVar(color: `#${string}`): RGBTailwindVar {
	const hex = color.replace(/^#/, "");
	const r = parseInt(hex.substring(0, 2), 16);
	const g = parseInt(hex.substring(2, 4), 16);
	const b = parseInt(hex.substring(4, 6), 16);
	return `${r} ${g} ${b}`;
}

const themes = {
	brand: {
		light: vars({
			"--color-bg": "255 255 255",
			"--color-bg-inverse": "28 28 30",
			"--color-bg-fill": "0 122 255",
			"--color-on-bg-fill": "255 255 255",
		}),
		dark: vars({
			"--color-bg": "28 28 30",
			"--color-bg-inverse": "255 255 255",
			"--color-bg-fill": "10 132 255",
			"--color-on-bg-fill": "255 255 255",
		}),
	},
	cold: {
		light: vars({
			"--color-bg": hexToRgbVar(colors.slate[50]),
			"--color-bg-inverse": hexToRgbVar(colors.slate[900]),
			"--color-bg-fill": "0 122 255",
			"--color-on-bg-fill": "255 255 255",
		}),
		dark: vars({
			"--color-bg": hexToRgbVar(colors.slate[900]),
			"--color-bg-inverse": hexToRgbVar(colors.slate[50]),
			"--color-bg-fill": "10 132 255",
			"--color-on-bg-fill": "255 255 255",
		}),
	},
};

export default function ThemeLayout({ children }: ThemeLayoutProps) {
	const { colorScheme: _colorScheme } = useColorScheme();
	const colorScheme = _colorScheme ?? "light";

	const theme = themes["brand"][colorScheme];

	return (
		<View
			style={theme}
			className="flex-1 items-center justify-center bg-app-bg">
			{children}
		</View>
	);
}

And I'm using it here:

import { Link } from "expo-router";
import { Pressable, Text, View } from "react-native";

import ThemeLayout from "@/components/ThemeLayout";

export default function RootPage() {
	return (
		<ThemeLayout>
			<Text className="text-4xl font-bold text-app-bg-inverse">Root page</Text>
			<View className="mt-2 flex flex-row gap-2">
				<Link
					asChild
					href="/onboarding/">
					<Pressable className="rounded-lg bg-fill px-4">
						<Text className="text-2xl font-semibold text-on-bg-fill">Get started</Text>
					</Pressable>
				</Link>
			</View>
		</ThemeLayout>
	);
}

DeluxeOwl avatar Feb 21 '24 11:02 DeluxeOwl

I have also observed this behaviour. The number of times the app re-renders doubles every time the iOS simulator Appearance Toggle is used.

For me the cause seems to be useColorScheme from NativeWind, used inside the root layout. Using the equivalent from react-native, the simulator behaves as expected.

Edit: This happens with Android emulator also.

tomhendra avatar Feb 21 '24 12:02 tomhendra

up

Natchii59 avatar Feb 29 '24 16:02 Natchii59

I have also noticed this issue and what @tomhendra added.

AkbarBakhshi avatar Apr 14 '24 12:04 AkbarBakhshi

You can use this patch to fix the issue:

diff --git a/node_modules/react-native-css-interop/dist/runtime/native/api.js b/node_modules/react-native-css-interop/dist/runtime/native/api.js
index 6db0750..f75b3e3 100644
--- a/node_modules/react-native-css-interop/dist/runtime/native/api.js
+++ b/node_modules/react-native-css-interop/dist/runtime/native/api.js
@@ -74,7 +74,10 @@ const remapProps = (component, mapping) => {
 exports.remapProps = remapProps;
 function useColorScheme() {
     const [effect, setEffect] = (0, react_1.useState)(() => ({
-        rerun: () => setEffect((s) => ({ ...s })),
+        rerun: () => setEffect((s) => {
+            (0, observable_1.cleanupEffect)(s)
+            return { ...s }
+        }),
         dependencies: new Set(),
     }));
     return {

IlyaPyatkin avatar Jun 17 '24 21:06 IlyaPyatkin

We are closing all pre-v4.1 issues now that v4.1 is released. If the problem is still happening with the latest v4.1, please open a new issue and reference this one in the description.

danstepanov avatar Sep 02 '24 23:09 danstepanov