Skip to content

Commit e7bbd7d

Browse files
committed
feat: go back to shadow nodes measurements
- Added useMemo for routes array with hideOneTab dependency - Added useMemo for renderScene to prevent unnecessary recreations - Created memoized navigationState object that only updates when index or routes change - This optimization prevents unnecessary re-renders when the component updates Signed-off-by: Oskar Kwaśniewski <[email protected]>
1 parent 25ea78a commit e7bbd7d

14 files changed

+379
-11
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
set(CMAKE_VERBOSE_MAKEFILE ON)
3+
4+
set(LIB_LITERAL RNCTabView)
5+
set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL})
6+
7+
set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
8+
set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp)
9+
set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni)
10+
set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL})
11+
12+
add_compile_options(
13+
-fexceptions
14+
-frtti
15+
-std=c++20
16+
-Wall
17+
-Wpedantic
18+
-Wno-gnu-zero-variadic-macro-arguments
19+
)
20+
21+
file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp)
22+
file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp)
23+
24+
add_library(
25+
${LIB_TARGET_NAME}
26+
SHARED
27+
${LIB_CUSTOM_SRCS}
28+
${LIB_CODEGEN_SRCS}
29+
)
30+
31+
target_include_directories(
32+
${LIB_TARGET_NAME}
33+
PUBLIC
34+
.
35+
${LIB_COMMON_DIR}
36+
${LIB_ANDROID_GENERATED_JNI_DIR}
37+
${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
38+
)
39+
40+
# https://github.com/react-native-community/discussions-and-proposals/discussions/816
41+
# This if-then-else can be removed once this library does not support version below 0.76
42+
if (REACTNATIVE_MERGED_SO)
43+
target_link_libraries(
44+
${LIB_TARGET_NAME}
45+
fbjni
46+
jsi
47+
reactnative
48+
)
49+
else()
50+
target_link_libraries(
51+
${LIB_TARGET_NAME}
52+
fbjni
53+
folly_runtime
54+
glog
55+
jsi
56+
react_codegen_rncore
57+
react_debug
58+
react_render_componentregistry
59+
react_render_core
60+
react_render_debug
61+
react_render_graphics
62+
react_render_imagemanager
63+
react_render_mapbuffer
64+
react_utils
65+
react_nativemodule_core
66+
rrc_image
67+
turbomodulejsijni
68+
rrc_view
69+
yoga
70+
)
71+
endif()
72+
73+
target_compile_options(
74+
${LIB_TARGET_NAME}
75+
PRIVATE
76+
-DLOG_TAG=\"ReactNative\"
77+
-fexceptions
78+
-frtti
79+
-std=c++20
80+
-Wall
81+
)
82+
83+
target_include_directories(
84+
${CMAKE_PROJECT_NAME}
85+
PUBLIC
86+
${CMAKE_CURRENT_SOURCE_DIR}
87+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <ReactCommon/JavaTurboModule.h>
4+
#include <ReactCommon/TurboModule.h>
5+
#include <jsi/jsi.h>
6+
#include <react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h>
7+
8+
namespace facebook::react {
9+
JSI_EXPORT
10+
std::shared_ptr<TurboModule> RNCTabView_ModuleProvider(
11+
const std::string &moduleName,
12+
const JavaTurboModule::InitParams &params);
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifdef __cplusplus
2+
3+
#pragma once
4+
5+
#include <react/renderer/components/RNCTabView/RNCTabViewShadowNode.h>
6+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
7+
8+
namespace facebook::react {
9+
10+
class RNCTabViewComponentDescriptor final : public ConcreteComponentDescriptor<RNCTabViewShadowNode>
11+
{
12+
#ifdef ANDROID
13+
public:
14+
RNCTabViewComponentDescriptor(const ComponentDescriptorParameters &parameters)
15+
: ConcreteComponentDescriptor(parameters), measurementsManager_(
16+
std::make_shared<RNCTabViewMeasurementsManager>(contextContainer_)) {}
17+
18+
void adopt(ShadowNode &shadowNode) const override
19+
{
20+
ConcreteComponentDescriptor::adopt(shadowNode);
21+
22+
auto &rncTabViewShadowNode =
23+
static_cast<RNCTabViewShadowNode &>(shadowNode);
24+
25+
// `RNCTabViewShadowNode` uses `RNCTabViewMeasurementsManager` to
26+
// provide measurements to Yoga.
27+
rncTabViewShadowNode.setSliderMeasurementsManager(
28+
measurementsManager_);
29+
30+
// All `RNCTabViewShadowNode`s must have leaf Yoga nodes with properly
31+
// setup measure function.
32+
rncTabViewShadowNode.enableMeasurement();
33+
}
34+
35+
private:
36+
const std::shared_ptr<RNCTabViewMeasurementsManager> measurementsManager_;
37+
#else
38+
public:
39+
RNCTabViewComponentDescriptor(const ComponentDescriptorParameters &parameters)
40+
: ConcreteComponentDescriptor(parameters) {}
41+
#endif
42+
43+
};
44+
45+
}
46+
47+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#ifdef ANDROID
2+
#include "RNCTabViewMeasurementsManager.h"
3+
4+
#include <fbjni/fbjni.h>
5+
#include <react/jni/ReadableNativeMap.h>
6+
#include <react/renderer/core/conversions.h>
7+
8+
9+
using namespace facebook::jni;
10+
11+
namespace facebook::react
12+
{
13+
Size RNCTabViewMeasurementsManager::measure(
14+
SurfaceId surfaceId,
15+
LayoutConstraints layoutConstraints) const
16+
{
17+
{
18+
std::scoped_lock lock(mutex_);
19+
if (hasBeenMeasured_)
20+
{
21+
return cachedMeasurement_;
22+
}
23+
}
24+
25+
const jni::global_ref<jobject>& fabricUIManager =
26+
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
27+
28+
static auto measure = facebook::jni::findClassStatic(
29+
"com/facebook/react/fabric/FabricUIManager")
30+
->getMethod<jlong(
31+
jint,
32+
jstring,
33+
ReadableMap::javaobject,
34+
ReadableMap::javaobject,
35+
ReadableMap::javaobject,
36+
jfloat,
37+
jfloat,
38+
jfloat,
39+
jfloat)>("measure");
40+
41+
auto minimumSize = layoutConstraints.minimumSize;
42+
auto maximumSize = layoutConstraints.maximumSize;
43+
44+
local_ref<JString> componentName = make_jstring("RNCTabView");
45+
46+
auto measurement = yogaMeassureToSize(measure(
47+
fabricUIManager,
48+
surfaceId,
49+
componentName.get(),
50+
nullptr,
51+
nullptr,
52+
nullptr,
53+
minimumSize.width,
54+
maximumSize.width,
55+
minimumSize.height,
56+
maximumSize.height));
57+
58+
std::scoped_lock lock(mutex_);
59+
cachedMeasurement_ = measurement;
60+
hasBeenMeasured_ = true;
61+
return measurement;
62+
}
63+
}
64+
65+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#ifdef __cplusplus
2+
3+
#ifdef ANDROID
4+
#pragma once
5+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
6+
#include <react/renderer/core/LayoutConstraints.h>
7+
#include <react/utils/ContextContainer.h>
8+
9+
namespace facebook::react
10+
{
11+
12+
class RNCTabViewMeasurementsManager
13+
{
14+
public:
15+
RNCTabViewMeasurementsManager(
16+
const ContextContainer::Shared &contextContainer)
17+
: contextContainer_(contextContainer) {}
18+
19+
Size measure(SurfaceId surfaceId, LayoutConstraints layoutConstraints) const;
20+
21+
private:
22+
const ContextContainer::Shared contextContainer_;
23+
mutable std::mutex mutex_;
24+
mutable bool hasBeenMeasured_ = false;
25+
mutable Size cachedMeasurement_{};
26+
};
27+
}
28+
29+
#endif
30+
31+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "RNCTabViewShadowNode.h"
2+
#include "RNCTabViewMeasurementsManager.h"
3+
4+
namespace facebook::react {
5+
6+
extern const char RNCTabViewComponentName[] = "RNCTabView";
7+
8+
#ifdef ANDROID
9+
void RNCTabViewShadowNode::setSliderMeasurementsManager(
10+
const std::shared_ptr<RNCTabViewMeasurementsManager> &
11+
measurementsManager)
12+
{
13+
ensureUnsealed();
14+
measurementsManager_ = measurementsManager;
15+
}
16+
17+
#pragma mark - LayoutableShadowNode
18+
19+
Size RNCTabViewShadowNode::measureContent(
20+
const LayoutContext & /*layoutContext*/,
21+
const LayoutConstraints &layoutConstraints) const
22+
{
23+
return measurementsManager_->measure(getSurfaceId(), layoutConstraints);
24+
}
25+
26+
#endif
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifdef __cplusplus
2+
3+
#pragma once
4+
5+
#include <jsi/jsi.h>
6+
#include <react/renderer/components/RNCTabView/RNCTabViewState.h>
7+
#include <react/renderer/components/RNCTabView/Props.h>
8+
#include <react/renderer/components/RNCTabView/EventEmitters.h>
9+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
10+
11+
#include "RNCTabViewMeasurementsManager.h"
12+
13+
namespace facebook::react {
14+
15+
JSI_EXPORT extern const char RNCTabViewComponentName[];
16+
17+
/*
18+
* `ShadowNode` for <RNCTabView> component.
19+
*/
20+
class JSI_EXPORT RNCTabViewShadowNode final
21+
: public ConcreteViewShadowNode<
22+
RNCTabViewComponentName,
23+
RNCTabViewProps,
24+
RNCTabViewEventEmitter,
25+
RNCTabViewState>
26+
{
27+
public:
28+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
29+
30+
#ifdef ANDROID
31+
void setSliderMeasurementsManager(
32+
const std::shared_ptr<RNCTabViewMeasurementsManager> &measurementsManager);
33+
34+
#pragma mark - LayoutableShadowNode
35+
36+
Size measureContent(
37+
const LayoutContext &layoutContext,
38+
const LayoutConstraints &layoutConstraints) const override;
39+
40+
private:
41+
std::shared_ptr<RNCTabViewMeasurementsManager> measurementsManager_;
42+
#endif
43+
44+
};
45+
46+
}
47+
48+
#endif
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifdef __cplusplus
2+
3+
#pragma once
4+
5+
#ifdef ANDROID
6+
#include <folly/dynamic.h>
7+
#include <react/renderer/mapbuffer/MapBuffer.h>
8+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
9+
#endif
10+
11+
namespace facebook::react {
12+
13+
class RNCTabViewState
14+
{
15+
public:
16+
RNCTabViewState() = default;
17+
18+
#ifdef ANDROID
19+
RNCTabViewState(RNCTabViewState const &previousState, folly::dynamic data) {};
20+
21+
folly::dynamic getDynamic() const
22+
{
23+
return {};
24+
};
25+
26+
MapBuffer getMapBuffer() const
27+
{
28+
return MapBufferBuilder::EMPTY();
29+
};
30+
#endif
31+
};
32+
33+
}
34+
35+
#endif

packages/react-native-bottom-tabs/ios/Fabric/RCTTabViewComponentView.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#import "RCTTabViewComponentView.h"
33

44
#import <react/renderer/components/RNCTabView/ComponentDescriptors.h>
5+
#import <react/renderer/components/RNCTabView/RNCTabViewComponentDescriptor.h>
56
#import <react/renderer/components/RNCTabView/EventEmitters.h>
67
#import <react/renderer/components/RNCTabView/Props.h>
78
#import <react/renderer/components/RNCTabView/RCTComponentViewHelpers.h>

packages/react-native-bottom-tabs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"files": [
2525
"src",
2626
"lib",
27+
"common",
2728
"android",
2829
"ios",
2930
"cpp",

0 commit comments

Comments
 (0)