Skip to content

Commit 1a9cceb

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Add sample component with state in RNTester (#34909)
Summary: Pull Request resolved: #34909 This Diff introduces a Sample component in RNTester which uses the NativeState to load some images. It is an example on how to use CustomNativeState In this first diff, I focused on the iOS side of things. The next diff will make this work with Android. ## Changelog [iOS][Added] - Introduce sample component which work with the native state. Reviewed By: cortinico Differential Revision: D39884926 fbshipit-source-id: 9323d751fd06a1bb8ff93af836d97010c2095833
1 parent d7c4136 commit 1a9cceb

14 files changed

+520
-2
lines changed

packages/rn-tester/BUCK

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ rn_library(
5151
"js",
5252
"NativeModuleExample",
5353
"NativeComponentExample",
54+
"NativeComponentWithState",
5455
"RCTTest",
5556
],
5657
excludes = [
@@ -85,6 +86,7 @@ fb_native.filegroup(
8586
],
8687
exclude = [
8788
"NativeComponentExample/**/*",
89+
"NativeComponentWithState/**/*",
8890
],
8991
),
9092
visibility = ["PUBLIC"],
@@ -321,3 +323,42 @@ rn_xplat_cxx_library2(
321323
"//xplat/js/react-native-github:RCTFabricComponentViewsBase",
322324
],
323325
)
326+
327+
rn_xplat_cxx_library2(
328+
name = "NativeComponentWithState",
329+
plugins_only = True,
330+
srcs = glob(
331+
[
332+
"NativeComponentWithState/ios/*.m",
333+
"NativeComponentWithState/ios/*.mm",
334+
"NativeComponentWithState/ios/*.cpp",
335+
],
336+
),
337+
headers = glob(
338+
[
339+
"NativeComponentWithState/ios/*.h",
340+
],
341+
),
342+
header_namespace = "",
343+
compiler_flags = [
344+
"-fexceptions",
345+
"-frtti",
346+
"-std=c++17",
347+
"-Wall",
348+
],
349+
contacts = ["oncall+react_native@xmail.facebook.com"],
350+
labels = [
351+
"pfh:ReactNative_CommonInfrastructurePlaceholder",
352+
"supermodule:xplat/default/public.react_native.infra",
353+
],
354+
plugins = [
355+
react_fabric_component_plugin_provider("RNTNativeComponentWithStateView", "RNTNativeComponentWithStateCls"),
356+
],
357+
plugins_header = "RCTFabricComponentsPlugins.h",
358+
reexport_all_header_dependencies = False,
359+
visibility = ["PUBLIC"],
360+
deps = [
361+
":generated_components-AppSpecs",
362+
"//xplat/js/react-native-github:RCTFabricComponentViewsBase",
363+
],
364+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
#
3+
# This source code is licensed under the MIT license found in the
4+
# LICENSE file in the root directory of this source tree.
5+
6+
require "json"
7+
8+
package = JSON.parse(File.read(File.join(__dir__, "../" "package.json")))
9+
10+
Pod::Spec.new do |s|
11+
s.name = "NativeComponentWithState"
12+
s.version = package["version"]
13+
s.summary = package["description"]
14+
s.description = "native-component-with-state"
15+
s.homepage = "https://github.com/sota000/my-native-view.git"
16+
s.license = "MIT"
17+
s.platforms = { :ios => "12.4", :tvos => "12.4" }
18+
s.compiler_flags = '-Wno-documentation -Wno-nullability-completeness'
19+
s.author = "Facebook, Inc. and its affiliates"
20+
s.source = { :git => "https://github.com/facebook/my-native-view.git", :tag => "#{s.version}" }
21+
s.pod_target_xcconfig = {
22+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"",
23+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
24+
}
25+
26+
s.source_files = "ios/**/*.{h,m,mm,cpp}"
27+
s.requires_arc = true
28+
29+
install_modules_dependencies(s)
30+
31+
# Enable codegen for this library
32+
use_react_native_codegen!(s, {
33+
:library_name => "NativeComponentWithStateSpec",
34+
:react_native_path => "../../../",
35+
:js_srcs_dir => "./js",
36+
:library_type => "components"
37+
})
38+
end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
9+
#include "RNTNativeComponentWithStateCustomShadowNode.h"
10+
11+
namespace facebook {
12+
namespace react {
13+
14+
/*
15+
* Descriptor for <RNTNativeComponentWithStateCustomComponentDescriptor>
16+
* component.
17+
*/
18+
class RNTNativeComponentWithStateCustomComponentDescriptor final
19+
: public ConcreteComponentDescriptor<
20+
RNTNativeComponentWithStateCustomShadowNode> {
21+
public:
22+
RNTNativeComponentWithStateCustomComponentDescriptor(
23+
ComponentDescriptorParameters const &parameters)
24+
: ConcreteComponentDescriptor(parameters),
25+
imageManager_(std::make_shared<ImageManager>(contextContainer_)) {}
26+
27+
void adopt(ShadowNode::Unshared const &shadowNode) const override {
28+
ConcreteComponentDescriptor::adopt(shadowNode);
29+
30+
auto compShadowNode =
31+
std::static_pointer_cast<RNTNativeComponentWithStateCustomShadowNode>(
32+
shadowNode);
33+
34+
// `RNTNativeComponentWithStateCustomShadowNode` uses `ImageManager` to
35+
// initiate image loading and communicate the loading state
36+
// and results to mounting layer.
37+
compShadowNode->setImageManager(imageManager_);
38+
}
39+
40+
private:
41+
const SharedImageManager imageManager_;
42+
};
43+
44+
} // namespace react
45+
} // namespace facebook
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "RNTNativeComponentWithStateCustomShadowNode.h"
9+
10+
#include <react/renderer/core/LayoutContext.h>
11+
12+
namespace facebook {
13+
namespace react {
14+
15+
extern const char RNTNativeComponentWithStateComponentName[] =
16+
"RNTNativeComponentWithState";
17+
18+
void RNTNativeComponentWithStateCustomShadowNode::setImageManager(
19+
const SharedImageManager &imageManager) {
20+
ensureUnsealed();
21+
imageManager_ = imageManager;
22+
}
23+
24+
void RNTNativeComponentWithStateCustomShadowNode::updateStateIfNeeded() {
25+
const auto &newImageSource = getImageSource();
26+
27+
auto const &currentState = getStateData();
28+
29+
auto imageSource = currentState.getImageSource();
30+
31+
bool anyChanged = newImageSource != imageSource;
32+
33+
if (!anyChanged) {
34+
return;
35+
}
36+
37+
// Now we are about to mutate the Shadow Node.
38+
ensureUnsealed();
39+
40+
// It is not possible to copy or move image requests from SliderLocalData,
41+
// so instead we recreate any image requests (that may already be in-flight?)
42+
// TODO: check if multiple requests are cached or if it's a net loss
43+
auto state = RNTNativeComponentWithStateState{
44+
newImageSource,
45+
imageManager_->requestImage(newImageSource, getSurfaceId())};
46+
setStateData(std::move(state));
47+
}
48+
49+
ImageSource RNTNativeComponentWithStateCustomShadowNode::getImageSource()
50+
const {
51+
return getConcreteProps().imageSource;
52+
}
53+
54+
void RNTNativeComponentWithStateCustomShadowNode::layout(
55+
LayoutContext layoutContext) {
56+
updateStateIfNeeded();
57+
ConcreteViewShadowNode::layout(layoutContext);
58+
}
59+
60+
} // namespace react
61+
} // namespace facebook
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <jsi/jsi.h>
11+
#include <react/renderer/components/AppSpecs/EventEmitters.h>
12+
#include <react/renderer/components/AppSpecs/Props.h>
13+
#include <react/renderer/components/AppSpecs/States.h>
14+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
15+
16+
#include <react/renderer/imagemanager/ImageManager.h>
17+
#include <react/renderer/imagemanager/primitives.h>
18+
19+
namespace facebook {
20+
namespace react {
21+
22+
JSI_EXPORT extern const char RNTNativeComponentWithStateComponentName[];
23+
24+
/*
25+
* `ShadowNode` for <Slider> component.
26+
*/
27+
class RNTNativeComponentWithStateCustomShadowNode final
28+
: public ConcreteViewShadowNode<
29+
RNTNativeComponentWithStateComponentName,
30+
RNTNativeComponentWithStateProps,
31+
RNTNativeComponentWithStateEventEmitter,
32+
RNTNativeComponentWithStateState> {
33+
public:
34+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
35+
36+
// Associates a shared `ImageManager` with the node.
37+
void setImageManager(const SharedImageManager &imageManager);
38+
39+
static RNTNativeComponentWithStateState initialStateData(
40+
ShadowNodeFragment const &fragment,
41+
ShadowNodeFamilyFragment const &familyFragment,
42+
ComponentDescriptor const &componentDescriptor) {
43+
auto imageSource = ImageSource{ImageSource::Type::Invalid};
44+
return {imageSource, {imageSource, nullptr}};
45+
}
46+
47+
#pragma mark - LayoutableShadowNode
48+
49+
void layout(LayoutContext layoutContext) override;
50+
51+
private:
52+
void updateStateIfNeeded();
53+
54+
ImageSource getImageSource() const;
55+
56+
SharedImageManager imageManager_;
57+
};
58+
59+
} // namespace react
60+
} // namespace facebook
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <React/RCTViewComponentView.h>
9+
#import <UIKit/UIKit.h>
10+
11+
NS_ASSUME_NONNULL_BEGIN
12+
13+
@interface RNTNativeComponentWithStateView : RCTViewComponentView
14+
15+
@end
16+
17+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)