V4: switching the color scheme becomes very laggy
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:
- Go to any screen that has the theme configured like in the above example
- Switch between light and dark a few times
- 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>
);
}
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.
up
I have also noticed this issue and what @tomhendra added.
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 {
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.