Yes, 66% faster.
Not "every screen in your app renders 66% faster" faster. If that happened, I would become impossible to talk to.
Also yes, I know this sounds funny in 2026.
We are in the era where AI news moves every five minutes. Claude Fable 5 launched and then got suspended a few days later. People are arguing about AGI-ish models, agents, whole apps being generated, and whatever the next insane benchmark is.
And I am here excited about React Native style flattening.
Fair.
But I still love this kind of work. Maybe it is not an "invention" in the dramatic movie-trailer sense, but making a shared framework path cheaper is still a real contribution. A lot of apps sit on top of these tiny internal paths. When one of them gets simpler and faster, that is still worth being happy about.
This one is about a very specific shared React Native path: flattening nested style arrays. The benchmark shows that path got a lot cheaper, and because style flattening is used in many places, that is still worth caring about.
It started from a very normal React Native thing: styles.
Every React Native developer has written something like this:
<View style={[styles.container, isActive && styles.active]} />
Nothing special. Just daily life.
Then you build reusable components, pass styles through props, merge internal styles with external styles, and suddenly your style prop is not just an array anymore. It can become an array inside another array, sometimes more than one level deep.
Basically:
You start with a clean style array.
Three components later, it looks like someone packed a suitcase by sitting on it.
I contributed a performance improvement to react/react-native, merged as PR #57203. It improves how React Native handles nested style arrays in flattenStyle.
The behavior stays the same. The difference is that React Native avoids creating extra intermediate objects while flattening nested arrays.
Why flattenStyle matters
At first, flattenStyle can sound like a small helper.
You may think it only matters when someone manually calls StyleSheet.flatten.
But React Native also uses this path internally. So it can show up in places like:
TextImageImageBackgroundTextInputTouchableOpacityScrollViewAnimated.ScrollView- animated props
- Fabric public instances
- developer tooling like the element inspector and React DevTools style resolving
So if a nested style array reaches these paths, improving flattenStyle means React Native does less work.
Important note: this does not mean every screen in every app becomes 66% faster.
Would be nice. I would print the benchmark and frame it.
The improvement is specifically for nested style-array flattening. Still, this is a shared path, and shared paths are exactly where small internal improvements can matter.
How nested styles happen
Here is a simple example:
<View
style={[
styles.container,
[styles.spacing, isActive && styles.active],
props.style,
]}
/>
This kind of thing can happen naturally in design-system components.
One component adds base styles. Another adds spacing. Another passes props.style. Maybe one of those values is already an array.
Nobody wakes up and says, "Today I will create nested style arrays."
It just happens.
Then React Native has to normalize it into one object.
That is the job of flattenStyle.
The old approach
Before the change, nested style arrays were flattened recursively.
That sounds fine, and it worked correctly.
The problem was that nested arrays could create temporary flattened objects. Then React Native had to merge those temporary objects into the final result.
The simplified version looked like this:
const flattened = flattenStyle(style[i]);
if (flattened != null) {
for (const key in flattened) {
result[key] = flattened[key];
}
}
So for nested arrays, React Native could do extra allocation and then extra copying.
Same result, more work.
It is like printing a document, scanning it, and then emailing the scan to yourself.
Technically it works.
Emotionally, no.

The change
The new implementation walks nested arrays directly into one result object.
Instead of flattening a nested array into a temporary object and then copying that object again, the recursive step writes into the same target result.
The important behavior still stays the same:
- object styles still work
- falsy values are still ignored
- nested arrays still work
- later styles still override earlier styles
That last one matters a lot.
Style order is part of the React Native API. This should still work exactly as developers expect:
<View style={[styles.base, styles.override]} />
If both styles define the same key, styles.override must win.
Performance is nice, but not if it quietly changes styling behavior. That would be the worst kind of "optimization".
A quick example
Take this style structure:
[
{color: "red", margin: 4},
[
{color: "blue"},
[{padding: 8}],
],
]
The final result should be:
{
color: "blue",
margin: 4,
padding: 8,
}
The old implementation could create temporary objects while resolving the nested arrays.
The new implementation reaches the same result while writing into one object.
Same output.
Less work.
That is the whole point.
Benchmark results
I made a small benchmark project outside the React Native repo so I could compare the old and new implementations in isolation:
tarikfp/rn-style-flatten-benchmark
These were the results from the PR:
| Scenario | Before | After | Change |
|---|---|---|---|
| nested single style array | 294.79 ms | 98.73 ms | 66.5% faster |
| nested merged style array | 278.54 ms | 122.06 ms | 56.2% faster |
The numbers are below 1 second, so milliseconds are easier to read here.
Again, this benchmark measures flattenStyle work for nested style arrays. It does not claim a full app render is 66% faster.
That distinction matters.
Benchmarks are useful, but only when they are honest about what they measure.
Validation
The contribution included focused unit coverage for flattenStyle.
The tests cover the behavior that should not change:
- object styles
- falsy entries
- nested style arrays
- override order
The benchmark app also had its own checks:
yarn test
yarn lint
yarn workspace style-flatten-benchmark-app tsc --noEmit
yarn bench:compare
And the React Native test command was:
yarn test packages/react-native/Libraries/StyleSheet/__tests__/flattenStyle-test.js --runInBand
The benchmark app was also built and installed on the iOS simulator.
Final thoughts
This is the kind of change I like in framework code.
Developers do not need to learn a new API. They do not need to rewrite components. They do not need to add some magic prop and hope for the best.
React Native just does less work for a case that already exists in real apps.
No behavior change.
No migration.
No drama.
Just fewer temporary objects in a shared path.
Sometimes that is the whole win.