Skip to content

Commit 92df955

Browse files
committed
fix: fast refresh crashing app
1 parent 72ba44d commit 92df955

File tree

3 files changed

+46
-33
lines changed

3 files changed

+46
-33
lines changed

cpp/StyledComputedFactory.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ namespace margelo::nitro::cssnitro {
2828
const std::string &variableScope,
2929
const std::string &containerScope,
3030
const std::vector<std::string> &validAttributeQueries) {
31+
32+
// Capture rerender by value (copy) so it persists through fast refresh
33+
// Capture shadowUpdates by pointer since it's a stable singleton
34+
auto shadowUpdatesPtr = &shadowUpdates;
35+
3136
auto computed = reactnativecss::Computed<Styled *>::create(
32-
[&styleRuleMap, classNames, componentId, &rerender, &shadowUpdates, variableScope, containerScope, validAttributeQueries](
37+
[&styleRuleMap, classNames, componentId, rerender, shadowUpdatesPtr, variableScope, containerScope, validAttributeQueries](
3338
Styled *const &prev,
3439
typename reactnativecss::Effect::GetProxy &get) {
3540
Styled *next = new Styled{};
@@ -113,17 +118,26 @@ namespace margelo::nitro::cssnitro {
113118
mergedImportantProps, false);
114119
}
115120

121+
// Only perform these actions if this is a recompute (prev exists)
116122
if (prev != nullptr) {
117-
delete prev;
118-
123+
// Check if we should rerender before deleting prev
119124
if (shouldRerender(*next)) {
120125
(void) rerender();
121126
}
122127

123-
if (next->style.has_value()) {
124-
// Notify ShadowTreeUpdateManager with the resolved style
125-
shadowUpdates.addUpdates(componentId, next->style.value());
126-
}
128+
// Notify ShadowTreeUpdateManager of style changes in a batch
129+
reactnativecss::Effect::batch([&]() {
130+
if (next->style.has_value()) {
131+
shadowUpdatesPtr->addUpdates(componentId, next->style.value());
132+
}
133+
if (next->importantStyle.has_value()) {
134+
shadowUpdatesPtr->addUpdates(componentId,
135+
next->importantStyle.value());
136+
}
137+
});
138+
139+
// Now safe to delete prev
140+
delete prev;
127141
}
128142

129143
return next;

example/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ StyleRegistry.addStyleSheet({
2525
// transitionDuration: "5s",
2626
},
2727
{
28-
selectionColor: "blue",
28+
selectionColor: "orange",
2929
},
3030
],
3131
},
@@ -48,7 +48,7 @@ export default function App() {
4848
return (
4949
<View style={styles.container}>
5050
<Text className="text-red-500" style={{ fontSize: 30 }} selectable>
51-
Multiply17: {multiply(3, 7)}
51+
Multiply28: {multiply(3, 7)}
5252
</Text>
5353
</View>
5454
);

src/components/Text/Text.native.tsx

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { Text as RNText } from "react-native";
33

44
import { createAnimatedComponent } from "react-native-reanimated";
55

6+
import { useElement } from "../../native/useElement";
7+
import { useDualRefs } from "../../native/useRef";
68
import { useStyledProps } from "../../native/useStyled";
7-
// import { useDualRefs } from "../../native/useRef";
8-
import { copyComponentProperties } from "../../utils";
9+
import { StyleRegistry } from "../../specs/StyleRegistry";
10+
import { copyComponentProperties, getDeepKeys } from "../../utils";
911

1012
const AnimatedText = createAnimatedComponent(RNText);
1113

@@ -15,28 +17,25 @@ export const Text = copyComponentProperties(
1517
const componentId = useId();
1618
const styled = useStyledProps(componentId, p.className, p);
1719

18-
// // const ref = useDualRefs(componentId, p.ref);
19-
20-
// if (p.style) {
21-
// StyleRegistry.updateComponentInlineStyleKeys(
22-
// componentId,
23-
// getDeepKeys(p.style),
24-
// );
25-
// }
26-
27-
// return useElement(AnimatedText, styled, {
28-
// ...styled.props,
29-
// ...p,
30-
// ...styled.importantProps,
31-
// // ref,
32-
// style:
33-
// styled.style || styled.importantStyle
34-
// ? [styled.style, p.style, styled.importantStyle]
35-
// : p.style,
36-
// });
37-
console.log("render", styled);
38-
39-
return <AnimatedText {...p} />;
20+
const ref = useDualRefs(componentId, p.ref);
21+
22+
if (p.style) {
23+
StyleRegistry.updateComponentInlineStyleKeys(
24+
componentId,
25+
getDeepKeys(p.style),
26+
);
27+
}
28+
29+
return useElement(AnimatedText, styled, {
30+
...styled.props,
31+
...p,
32+
...styled.importantProps,
33+
ref,
34+
style:
35+
styled.style || styled.importantStyle
36+
? [styled.style, p.style, styled.importantStyle]
37+
: p.style,
38+
});
4039
},
4140
);
4241

0 commit comments

Comments
 (0)