diff --git a/src/runtime/native/__tests__/container-queries.test.tsx b/src/runtime/native/__tests__/container-queries.test.tsx
index e0e6688..2dd262d 100644
--- a/src/runtime/native/__tests__/container-queries.test.tsx
+++ b/src/runtime/native/__tests__/container-queries.test.tsx
@@ -5,6 +5,45 @@ import { registerCSS } from "react-native-css/jest";
const parentID = "parent";
const childID = "child";
+test("Unnamed containers", () => {
+ registerCSS(`
+ :root, :host {
+ --color-white: #fff;
+ }
+ .\\@container {
+ container-type: inline-size;
+ }
+ .\\@sm\\:text-white {
+ @container (width >= 24rem) {
+ color: var(--color-white);
+ }
+ }
+ `);
+
+ render(
+
+
+ ,
+ );
+
+ const parent = screen.getByTestId(parentID);
+ const child = screen.getByTestId(childID);
+
+ expect(child).toHaveStyle(undefined);
+
+ // Jest does not fire layout events, so we need to manually
+ fireEvent(parent, "layout", {
+ nativeEvent: {
+ layout: {
+ width: 500,
+ height: 200,
+ },
+ },
+ });
+
+ expect(child).toHaveStyle({ color: "#fff" });
+});
+
test("container query width", () => {
registerCSS(`
.container {
diff --git a/src/runtime/native/__tests__/grouping.test.tsx b/src/runtime/native/__tests__/grouping.test.tsx
index 3c9f844..68f1056 100644
--- a/src/runtime/native/__tests__/grouping.test.tsx
+++ b/src/runtime/native/__tests__/grouping.test.tsx
@@ -10,24 +10,24 @@ const childID = "child";
jest.useFakeTimers();
test("groups", () => {
- registerCSS(
- `.group\\/item .my-class {
+ registerCSS(`
+ .group\\/item .my-class {
color: red;
- }`,
- );
+ }
+ `);
- const { rerender, getByTestId } = render(
-
+ render(
+
,
);
- const component = getByTestId(childID);
+ const component = screen.getByTestId(childID);
expect(component.props.style).toStrictEqual({ color: "#f00" });
- rerender(
-
+ screen.rerender(
+
,
);
diff --git a/src/runtime/native/__tests__/upgrading.test.tsx b/src/runtime/native/__tests__/upgrading.test.tsx
index d5ef196..4793d2c 100644
--- a/src/runtime/native/__tests__/upgrading.test.tsx
+++ b/src/runtime/native/__tests__/upgrading.test.tsx
@@ -41,12 +41,12 @@ test("adding a group", () => {
expect(log.mock.calls).toEqual([
[
- "ReactNativeCss: className 'group' added a container after the initial render. This causes the components state to be reset and all children be re-mounted. This will cause unexpected behavior. Use the className 'will-change-container' to avoid this warning. If this was caused by sibling components being added/removed, use a 'key' prop so React can track the component correctly.",
+ "ReactNativeCss: className 'group' added or removed a container after the initial render. This causes the components state to be reset and all children be re-mounted. This will cause unexpected behavior. Use the className 'will-change-container' to avoid this warning. If this was caused by sibling components being added/removed, use a 'key' prop so React can track the component correctly.",
],
]);
});
-test.only("will-change-container", () => {
+test("will-change-container", () => {
registerCSS(
`.group .my-class {
color: red;
@@ -69,9 +69,6 @@ test.only("will-change-container", () => {
,
);
- expect(log.mock.calls).toEqual([
- [
- "ReactNativeCss: className 'group' added or removed a container after the initial render. This causes the components state to be reset and all children be re-mounted. This will cause unexpected behavior. Use the className 'will-change-container' to avoid this warning. If this was caused by sibling components being added/removed, use a 'key' prop so React can track the component correctly.",
- ],
- ]);
+ // There shouldn't be any error, as we continued to have a container
+ expect(log.mock.calls).toEqual([]);
});
diff --git a/src/runtime/native/injection.ts b/src/runtime/native/injection.ts
index 24a3f03..3850aad 100644
--- a/src/runtime/native/injection.ts
+++ b/src/runtime/native/injection.ts
@@ -3,6 +3,7 @@ import type {
ReactNativeCssStyleSheet,
StyleRuleSet,
} from "../../compiler";
+import { DEFAULT_CONTAINER_NAME } from "./conditions/container-query";
import {
family,
observable,
@@ -27,6 +28,36 @@ StyleCollection.keyframes = family>(() => {
StyleCollection.inject = function (options: ReactNativeCssStyleSheet) {
observableBatch.current = new Set();
+ StyleCollection.styles("will-change-variable").set([
+ {
+ s: [0],
+ v: [],
+ },
+ ]);
+
+ StyleCollection.styles("will-change-container").set([
+ {
+ s: [0],
+ c: [DEFAULT_CONTAINER_NAME],
+ },
+ ]);
+
+ StyleCollection.styles("will-change-animation").set([
+ {
+ s: [0],
+ a: true,
+ },
+ ]);
+
+ StyleCollection.styles("will-change-pressable").set([
+ {
+ s: [0],
+ p: {
+ h: 1,
+ },
+ },
+ ]);
+
if (options.s) {
for (const style of options.s) {
StyleCollection.styles(style[0]).set(style[1]);
@@ -99,33 +130,3 @@ function isDeepEqual(a: unknown, b: unknown): boolean {
return true;
}
-
-StyleCollection.styles("will-change-variable").set([
- {
- s: [0],
- v: [],
- },
-]);
-
-StyleCollection.styles("will-change-container").set([
- {
- s: [0],
- c: [],
- },
-]);
-
-StyleCollection.styles("will-change-animation").set([
- {
- s: [0],
- a: true,
- },
-]);
-
-StyleCollection.styles("will-change-pressable").set([
- {
- s: [0],
- p: {
- h: 1,
- },
- },
-]);
diff --git a/src/runtime/native/react/rules.ts b/src/runtime/native/react/rules.ts
index cbe33fb..0d5e53a 100644
--- a/src/runtime/native/react/rules.ts
+++ b/src/runtime/native/react/rules.ts
@@ -12,6 +12,7 @@ import {
hoverFamily,
VAR_SYMBOL,
weakFamily,
+ type ContainerContextValue,
type VariableContextValue,
} from "../reactivity";
import { stylesFamily } from "../styles";
@@ -36,8 +37,8 @@ export function updateRules(
let usesVariables = false;
- let variables = state.variables ? inheritedVariables : undefined;
- let containers = state.containers ? inheritedContainers : undefined;
+ let variables: VariableContextValue | undefined;
+ let containers: ContainerContextValue | undefined;
const inlineVariables = new Set();
let animated = false;
@@ -101,6 +102,16 @@ export function updateRules(
usesVariables ||= Boolean(rule.dv);
+ // We do this even if the rule doesn't match so we can maintain a consistent render tree
+ // We we need to inject React context
+ if (rule.v) {
+ variables ??= inheritedVariables;
+ }
+
+ if (rule.c) {
+ containers ??= inheritedContainers;
+ }
+
if (
!testRule(
rule,
@@ -114,11 +125,8 @@ export function updateRules(
}
if (rule.v) {
- // We're going to set a value, so we need to create a new object
if (variables === inheritedVariables) {
variables = { ...inheritedVariables };
- } else {
- variables ??= { ...inheritedVariables };
}
for (const v of rule.v) {
@@ -199,6 +207,7 @@ export function updateRules(
guards,
animated,
pressable,
+ variables,
};
}