Skip to content

Commit 05eb5cd

Browse files
committed
fix: restore Android View props on React Native 0.87
1 parent b7e776c commit 05eb5cd

7 files changed

Lines changed: 56 additions & 4 deletions

File tree

‎apps/example/__tests__/nitro.views.harness.tsx‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ describe('TestView', () => {
187187
callbackSawUpdatedState = mountedView?.hasBeenCalled === true
188188
callbackFinished.resolve(undefined)
189189
})
190+
const wrappedCallback = callback(onSomeCallback)
191+
const callbackWithMetadata = {
192+
...wrappedCallback,
193+
// Nitro-only values must bypass folly conversion, which rejects BigInts.
194+
metadata: 123n,
195+
}
190196

191197
await render(
192198
<TestView
@@ -196,7 +202,7 @@ describe('TestView', () => {
196202
isBlue={true}
197203
hasBeenCalled={false}
198204
colorScheme="dark"
199-
someCallback={callback(onSomeCallback)}
205+
someCallback={callbackWithMetadata}
200206
onLayout={({ nativeEvent }) => layout.resolve(nativeEvent.layout)}
201207
/>,
202208
{ timeout: RENDER_TIMEOUT }

‎apps/example/android/app/src/main/java/com/nitroexample/MainApplication.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsProvider
1414

1515
private val stableFlagsWithNitroViewRecycling: ReactNativeFeatureFlagsProvider =
1616
object : ReactNativeFeatureFlagsProvider by ReactNativeFeatureFlagsOverrides_RNOSS_Stable_Android() {
17+
// Exercise Nitro's explicit dynamic-props initialization on RN 0.84-0.86.
18+
override fun enableExclusivePropsUpdateAndroid(): Boolean = true
19+
1720
override fun enablePreparedTextLayout(): Boolean = false
1821

1922
override fun enableViewRecycling(): Boolean = true

‎packages/nitrogen/src/views/CppHybridViewComponent.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ ${createFileMetadataString(`${component}.cpp`)}
185185
#include "${component}.hpp"
186186
187187
#include <NitroModules/NitroHash.hpp>
188+
#include <NitroModules/RawPropsCompat.hpp>
188189
#include <NitroModules/ReactProp.hpp>
189190
190191
namespace ${namespace} {
@@ -196,7 +197,11 @@ namespace ${namespace} {
196197
${propsClassName}::${propsClassName}(const react::PropsParserContext& context,
197198
${ctorIndent} const ${propsClassName}& sourceProps,
198199
${ctorIndent} const react::RawProps& rawProps):
199-
${indent(propInitializers.join(',\n'), ' ')} { }
200+
${indent(propInitializers.join(',\n'), ' ')} {
201+
#ifdef ANDROID
202+
nitro::RawPropsCompat::initializeDynamicProps(*this, sourceProps, rawProps, filterObjectKeys);
203+
#endif
204+
}
200205
201206
bool ${propsClassName}::filterObjectKeys(const std::string& propName) {
202207
switch (hashString(propName)) {

‎packages/react-native-nitro-modules/cpp/views/RawPropsCompat.cpp‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@
99
#endif
1010

1111
#include <cxxreact/ReactNativeVersion.h>
12+
#include <react/renderer/core/Props.h>
1213
#include <react/renderer/core/RawProps.h>
1314
#include <react/renderer/core/RawPropsParser.h>
1415

16+
#if defined(ANDROID) && REACT_NATIVE_VERSION_MAJOR == 0 && REACT_NATIVE_VERSION_MINOR >= 84 && REACT_NATIVE_VERSION_MINOR < 87
17+
#include <react/featureflags/ReactNativeFeatureFlags.h>
18+
#endif
19+
1520
namespace margelo::nitro::RawPropsCompat {
1621

1722
const facebook::react::RawValue* at(const facebook::react::RawProps& props, const char* name) {
@@ -32,4 +37,20 @@ facebook::react::RawPropsParser makePropsParser() {
3237
#endif
3338
}
3439

40+
void initializeDynamicProps([[maybe_unused]] facebook::react::Props& props, [[maybe_unused]] const facebook::react::Props& sourceProps,
41+
[[maybe_unused]] const facebook::react::RawProps& rawProps,
42+
[[maybe_unused]] bool (*filterObjectKeys)(const std::string&)) {
43+
#ifdef ANDROID
44+
#if REACT_NATIVE_VERSION_MAJOR > 0 || REACT_NATIVE_VERSION_MINOR >= 87
45+
// Since React Native 0.87, the base constructor no longer initializes dynamic props.
46+
props.initializeDynamicProps(sourceProps, rawProps, filterObjectKeys);
47+
#elif REACT_NATIVE_VERSION_MINOR >= 84
48+
// React Native 0.84-0.86 skips initialization only when exclusive props updates are enabled.
49+
if (facebook::react::ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid()) {
50+
props.initializeDynamicProps(sourceProps, rawProps, filterObjectKeys);
51+
}
52+
#endif
53+
#endif
54+
}
55+
3556
} // namespace margelo::nitro::RawPropsCompat

‎packages/react-native-nitro-modules/cpp/views/RawPropsCompat.hpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
#pragma once
66

7+
#include <string>
8+
79
namespace facebook::react {
10+
class Props;
811
class RawProps;
912
class RawPropsParser;
1013
class RawValue;
@@ -15,4 +18,8 @@ namespace margelo::nitro::RawPropsCompat {
1518
const facebook::react::RawValue* at(const facebook::react::RawProps& props, const char* name);
1619
facebook::react::RawPropsParser makePropsParser();
1720

21+
// Initialize Android's dynamic props only when the React Native constructor has not already done so.
22+
void initializeDynamicProps(facebook::react::Props& props, const facebook::react::Props& sourceProps,
23+
const facebook::react::RawProps& rawProps, bool (*filterObjectKeys)(const std::string&));
24+
1825
} // namespace margelo::nitro::RawPropsCompat

‎packages/react-native-nitro-test/nitrogen/generated/shared/c++/views/HybridRecyclableTestViewComponent.cpp‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "HybridRecyclableTestViewComponent.hpp"
99

1010
#include <NitroModules/NitroHash.hpp>
11+
#include <NitroModules/RawPropsCompat.hpp>
1112
#include <NitroModules/ReactProp.hpp>
1213

1314
namespace margelo::nitro::test::views {
@@ -22,7 +23,11 @@ namespace margelo::nitro::test::views {
2223
react::ViewProps(context, sourceProps, rawProps, filterObjectKeys),
2324
isBlue(nitro::ReactProp<bool>::fromRawValue("RecyclableTestView", "isBlue", rawProps, sourceProps.isBlue)),
2425
nativeDefaultValue(nitro::ReactProp<std::optional<double>>::fromRawValue("RecyclableTestView", "nativeDefaultValue", rawProps, sourceProps.nativeDefaultValue)),
25-
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridRecyclableTestViewSpec>& /* ref */)>>>::fromRawValue("RecyclableTestView", "hybridRef", rawProps, sourceProps.hybridRef)) { }
26+
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridRecyclableTestViewSpec>& /* ref */)>>>::fromRawValue("RecyclableTestView", "hybridRef", rawProps, sourceProps.hybridRef)) {
27+
#ifdef ANDROID
28+
nitro::RawPropsCompat::initializeDynamicProps(*this, sourceProps, rawProps, filterObjectKeys);
29+
#endif
30+
}
2631

2732
bool HybridRecyclableTestViewProps::filterObjectKeys(const std::string& propName) {
2833
switch (hashString(propName)) {

‎packages/react-native-nitro-test/nitrogen/generated/shared/c++/views/HybridTestViewComponent.cpp‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "HybridTestViewComponent.hpp"
99

1010
#include <NitroModules/NitroHash.hpp>
11+
#include <NitroModules/RawPropsCompat.hpp>
1112
#include <NitroModules/ReactProp.hpp>
1213

1314
namespace margelo::nitro::test::views {
@@ -25,7 +26,11 @@ namespace margelo::nitro::test::views {
2526
colorScheme(nitro::ReactProp<ColorScheme>::fromRawValue("TestView", "colorScheme", rawProps, sourceProps.colorScheme)),
2627
someCallback(nitro::ReactProp<std::function<void()>>::fromRawValue("TestView", "someCallback", rawProps, sourceProps.someCallback)),
2728
nativeDefaultValue(nitro::ReactProp<std::optional<double>>::fromRawValue("TestView", "nativeDefaultValue", rawProps, sourceProps.nativeDefaultValue)),
28-
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridTestViewSpec>& /* ref */)>>>::fromRawValue("TestView", "hybridRef", rawProps, sourceProps.hybridRef)) { }
29+
hybridRef(nitro::ReactProp<std::optional<std::function<void(const std::shared_ptr<HybridTestViewSpec>& /* ref */)>>>::fromRawValue("TestView", "hybridRef", rawProps, sourceProps.hybridRef)) {
30+
#ifdef ANDROID
31+
nitro::RawPropsCompat::initializeDynamicProps(*this, sourceProps, rawProps, filterObjectKeys);
32+
#endif
33+
}
2934

3035
bool HybridTestViewProps::filterObjectKeys(const std::string& propName) {
3136
switch (hashString(propName)) {

0 commit comments

Comments
 (0)