Skip to content

feat: skip unsafe Unistyles dynamic styles#22

Open
NikhilRW wants to merge 1 commit into
kuatsu:mainfrom
NikhilRW:main
Open

feat: skip unsafe Unistyles dynamic styles#22
NikhilRW wants to merge 1 commit into
kuatsu:mainfrom
NikhilRW:main

Conversation

@NikhilRW

@NikhilRW NikhilRW commented May 2, 2026

Copy link
Copy Markdown

Adds Unistyles-aware safety checks to the React Native Boost Babel optimizer.

This change detects react-native-unistyles styles created with StyleSheet.create(...) and prevents unsafe optimization when those styles are dynamic. Dynamic Unistyles styles can depend on theme values, runtime state, function styles, variants, conditionals, or other runtime expressions, so replacing those components with Boost native components can break style updates.

The optimizer now:

  • Skips Text and View when they use dynamic Unistyles styles.
  • Allows optimization for provably static Unistyles object styles.
  • Keeps the normal Boost runtime path using NativeText and NativeView.
  • Does not add a Unistyles compatibility component replacement path.

Examples skipped:

StyleSheet.create((theme) => ({
  title: { color: theme.colors.text },
}));
StyleSheet.create({
  title: (active) => ({ color: active ? 'red' : 'blue' }),
});

Tests run:

pnpm exec oxlint --fix
pnpm --filter react-native-boost typecheck
pnpm --filter react-native-boost test -- --run src/plugin/optimizers/text/__tests__/index.test.ts src/plugin/optimizers/view/__tests__/index.test.ts

Copilot AI review requested due to automatic review settings May 2, 2026 19:40
@netlify

netlify Bot commented May 2, 2026

Copy link
Copy Markdown

Deploy Preview for react-native-boost ready!

Name Link
🔨 Latest commit 9a4db95
🔍 Latest deploy log https://app.netlify.com/projects/react-native-boost/deploys/69f6532711d0ab0008323c30
😎 Deploy Preview https://deploy-preview-22--react-native-boost.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the react-native-boost Babel plugin to detect react-native-unistyles styles in JSX and avoid optimizing View/Text components when the Unistyles styles are dynamic (runtime-dependent), while still allowing optimization for provably static Unistyles styles. It also includes a small Android event payload adjustment in react-native-time-to-render.

Changes:

  • Add Unistyles style detection/classification (none/static/dynamic) in the plugin’s attribute utilities.
  • Skip View/Text optimizations when dynamic Unistyles styles are detected; allow View optimization when styles are static Unistyles.
  • Add optimizer fixture coverage for Unistyles style scenarios (static vs dynamic) for both View and Text.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/react-native-time-to-render/android/src/main/java/com/timetorender/OnMarkerPaintedEvent.kt Adjusts event “target” field to use viewTag directly.
packages/react-native-boost/src/plugin/utils/common/attributes.ts Introduces Unistyles style detection logic and status classification helpers.
packages/react-native-boost/src/plugin/optimizers/view/index.ts Skips optimization on dynamic Unistyles styles; conditionally relaxes style blacklisting when Unistyles styles are static.
packages/react-native-boost/src/plugin/optimizers/view/tests/fixtures/unistyles-styles/code.js New fixture input for View optimizer covering Unistyles styles.
packages/react-native-boost/src/plugin/optimizers/view/tests/fixtures/unistyles-styles/output.js Expected output for View optimizer with Unistyles styles.
packages/react-native-boost/src/plugin/optimizers/text/index.ts Skips optimization on dynamic Unistyles styles for Text.
packages/react-native-boost/src/plugin/optimizers/text/tests/fixtures/unistyles-styles/code.js New fixture input for Text optimizer covering Unistyles styles.
packages/react-native-boost/src/plugin/optimizers/text/tests/fixtures/unistyles-styles/output.js Expected output for Text optimizer with Unistyles styles.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +216 to +225
if (t.isCallExpression(expression)) {
let status: UnistylesStyleStatus = t.isExpression(expression.callee)
? getExpressionUnistylesStyleStatus(path, expression.callee, seen)
: 'none';

for (const argument of expression.arguments) {
if (!t.isExpression(argument)) continue;
status = mergeUnistylesStyleStatus(status, getExpressionUnistylesStyleStatus(path, argument, seen));
if (status !== 'none') return 'dynamic';
}
Comment on lines +62 to +66
shouldBail: () =>
hasBlacklistedProperty(
path,
usesUnistylesStyle ? viewBlacklistedPropertiesWithoutStyle : viewBlacklistedProperties
),
@mfkrause

mfkrause commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Hey, thanks a lot for your PR! This is a tricky one; a couple of things:

  1. The static/dynamic classification you're trying to do makes sense, but in my opinion is incomplete and unsafe. For example, a style definition of { width: { sm: 100, lg: 200 } } that utilizes Unistyles' breakpoints feature would be classified as static and would therefore not cause react-native-boost to bail, potentially optimizing the component. That in return would cause Unistyles to be unable to update the component on breakpoint changes. There's other similar problems too, breakpoints are only one example. I'm not entirely sure we can catch these through the Babel plugin, however.
  2. Additionally, stylesheet detection is same-file only; the same Babel limitation we're already facing with unknown cross-file ancestors of View components. So, a stylesheet defined in another file with dynamic styles would be classified as none by this implementation and cause react-native-boost to optimize it, again making unsafe optimizations.
  3. We're currently bailing on all View components that have style props (although I honestly can't remember if there's a reason for this at all, I'd have to look into this again). Your implementation "works around this gate", effectively bypassing it. This should therefore either be documented with reasoning, or we should work on dropping the style prop bail-out for View components completely. (This is also flagged by GitHub Copilot above.)

However, I do agree that Unistyles is currently effectively broken. The timings of their Babel plugin and our Babel plugin "unfortunately" work in our favor, so that react-native-boost always rewrites Text and View components, and Unistyles doesn't (usually, they also rewrite them to their own factory components, but can't do that with react-native-boost in the loop, currently). We therefore do need some sort of remedy for this.

I'll dig into this properly alongside some other optimizations I have planned, and figure out whether there's any way we can safely optimize Unistyles-managed components at all, or if Unistyles needs to be documented as a known incompatibility for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants