forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
236 lines (216 loc) · 46.2 KB
/
index.html
File metadata and controls
236 lines (216 loc) · 46.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/><title>Communication between native and React Native · React Native</title><meta name="viewport" content="width=device-width"/><meta name="generator" content="Docusaurus"/><meta name="description" content="In [Integrating with Existing Apps guide](/docs/0.61/integration-with-existing-apps) and [Native UI Components guide](/docs/0.61/native-components-ios) we learn how to embed React Native in a native component and vice versa. When we mix native and React Native components, we'll eventually find a need to communicate between these two worlds. Some ways to achieve that have been already mentioned in other guides. This article summarizes available techniques."/><meta name="docsearch:version" content="0.61"/><meta name="docsearch:language" content="en"/><meta property="og:title" content="Communication between native and React Native · React Native"/><meta property="og:type" content="website"/><meta property="og:url" content="https://reactnative.dev/"/><meta property="og:description" content="In [Integrating with Existing Apps guide](/docs/0.61/integration-with-existing-apps) and [Native UI Components guide](/docs/0.61/native-components-ios) we learn how to embed React Native in a native component and vice versa. When we mix native and React Native components, we'll eventually find a need to communicate between these two worlds. Some ways to achieve that have been already mentioned in other guides. This article summarizes available techniques."/><meta property="og:image" content="https://reactnative.dev/img/logo-og.png"/><meta name="twitter:card" content="summary"/><meta name="twitter:image" content="https://reactnative.dev/img/logo-og.png"/><link rel="shortcut icon" href="/img/favicon.ico"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"/><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/solarized-dark.min.css"/><link rel="alternate" type="application/atom+xml" href="https://reactnative.dev/blog/atom.xml" title="React Native Blog ATOM Feed"/><link rel="alternate" type="application/rss+xml" href="https://reactnative.dev/blog/feed.xml" title="React Native Blog RSS Feed"/><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-41298772-2', 'auto');
ga('send', 'pageview');
</script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/focus-visible@5.0.2/dist/focus-visible.min.js"></script><script type="text/javascript" src="https://snack.expo.io/embed.js"></script><script type="text/javascript" src="https://platform.twitter.com/widgets.js"></script><script type="text/javascript" src="https://buttons.github.io/buttons.js"></script><script type="text/javascript" src="/js/codeblocks.js"></script><script type="text/javascript" src="/js/tabs.js"></script><script type="text/javascript" src="/js/docs-rating.js"></script><script type="text/javascript" src="/js/announcement.js"></script><script src="https://unpkg.com/vanilla-back-to-top@7.1.14/dist/vanilla-back-to-top.min.js"></script><script>
document.addEventListener('DOMContentLoaded', function() {
addBackToTop(
{"zIndex":100}
)
});
</script><script src="/js/scrollSpy.js"></script><link rel="stylesheet" href="/css/prism.css"/><link rel="stylesheet" href="/css/main.css"/><script src="/js/codetabs.js"></script></head><body class="sideNavVisible separateOnPageNav"><div class="fixedHeaderContainer"><div class="headerWrapper wrapper"><header><a href="/"><img class="logo" src="/img/header_logo.svg" alt="React Native"/><h2 class="headerTitleWithLogo">React Native</h2></a><a href="/versions"><h3>0.61</h3></a><div class="navigationWrapper navigationSlider"><nav class="slidingNav"><ul class="nav-site nav-site-internal"><li class="siteNavGroupActive"><a href="/docs/0.61/getting-started" target="_self">Docs</a></li><li class=""><a href="/docs/0.61/components-and-apis" target="_self">Components</a></li><li class=""><a href="/docs/0.61/accessibilityinfo" target="_self">API</a></li><li class=""><a href="/help" target="_self">Community</a></li><li class=""><a href="/blog/" target="_self">Blog</a></li><li class="navSearchWrapper reactNavSearchWrapper"><input type="text" id="search_input_react" placeholder="Search" title="Search"/></li><li class=""><a href="https://github.com/facebook/react-native" target="_self">GitHub</a></li></ul></nav></div></header></div></div><div class="navPusher"><div class="docMainWrapper wrapper"><div class="docsNavContainer" id="docsNav"><nav class="toc"><div class="toggleNav"><section class="navWrapper wrapper"><div class="navBreadcrumb wrapper"><div class="navToggle" id="navToggler"><div class="hamburger-menu"><div class="line1"></div><div class="line2"></div><div class="line3"></div></div></div><h2><i>›</i><span>Guides (iOS)</span></h2><div class="tocToggler" id="tocToggler"><i class="icon-toc"></i></div></div><div class="navGroups"><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">The Basics<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/0.61/getting-started">Getting Started</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/tutorial">Learn the Basics</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/props">Props</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/state">State</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/style">Style</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/height-and-width">Height and Width</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/flexbox">Layout with Flexbox</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/handling-text-input">Handling Text Input</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/handling-touches">Handling Touches</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/using-a-scrollview">Using a ScrollView</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/using-a-listview">Using List Views</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/network">Networking</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/more-resources">More Resources</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Guides<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/0.61/fast-refresh">Fast Refresh</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/platform-specific-code">Platform Specific Code</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/navigation">Navigating Between Screens</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/images">Images</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/animations">Animations</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/accessibility">Accessibility</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/improvingux">Improving User Experience</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/optimizing-flatlist-configuration">Optimizing Flatlist Configuration</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/timers">Timers</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/debugging">Debugging</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/performance">Performance</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/gesture-responder-system">Gesture Responder System</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/javascript-environment">JavaScript Environment</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/typescript">Using TypeScript with React Native</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/direct-manipulation">Direct Manipulation</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/colors">Color Reference</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/integration-with-existing-apps">Integration with Existing Apps</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/building-for-tv">Building For TV Devices</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/running-on-device">Running On Device</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/upgrading">Upgrading to new React Native versions</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/troubleshooting">Troubleshooting</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/native-modules-setup">Native Modules Setup</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/out-of-tree-platforms">Out-of-Tree Platforms</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Guides (iOS)<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/0.61/native-modules-ios">Native Modules</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/native-components-ios">Native UI Components</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/linking-libraries-ios">Linking Libraries</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/running-on-simulator-ios">Running On Simulator</a></li><li class="navListItem navListItemActive"><a class="navItem" href="/docs/0.61/communication-ios">Communication between native and React Native</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/app-extensions">App Extensions</a></li></ul></div><div class="navGroup"><h3 class="navGroupCategoryTitle collapsible">Guides (Android)<span class="arrow"><svg width="24" height="24" viewBox="0 0 24 24"><path fill="#565656" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path><path d="M0 0h24v24H0z" fill="none"></path></svg></span></h3><ul class="hide"><li class="navListItem"><a class="navItem" href="/docs/0.61/native-modules-android">Native Modules</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/native-components-android">Native UI Components</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/headless-js-android">Headless JS</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/signed-apk-android">Publishing to Google Play Store</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/removing-default-permissions">Removing Default Permissions</a></li><li class="navListItem"><a class="navItem" href="/docs/0.61/hermes">Using Hermes</a></li></ul></div></div></section></div><script>
var coll = document.getElementsByClassName('collapsible');
var checkActiveCategory = true;
for (var i = 0; i < coll.length; i++) {
var links = coll[i].nextElementSibling.getElementsByTagName('*');
if (checkActiveCategory){
for (var j = 0; j < links.length; j++) {
if (links[j].classList.contains('navListItemActive')){
coll[i].nextElementSibling.classList.toggle('hide');
coll[i].childNodes[1].classList.toggle('rotate');
checkActiveCategory = false;
break;
}
}
}
coll[i].addEventListener('click', function() {
var arrow = this.childNodes[1];
arrow.classList.toggle('rotate');
var content = this.nextElementSibling;
content.classList.toggle('hide');
});
}
document.addEventListener('DOMContentLoaded', function() {
createToggler('#navToggler', '#docsNav', 'docsSliderActive');
createToggler('#tocToggler', 'body', 'tocActive');
var headings = document.querySelector('.toc-headings');
headings && headings.addEventListener('click', function(event) {
var el = event.target;
while(el !== headings){
if (el.tagName === 'A') {
document.body.classList.remove('tocActive');
break;
} else{
el = el.parentNode;
}
}
}, false);
function createToggler(togglerSelector, targetSelector, className) {
var toggler = document.querySelector(togglerSelector);
var target = document.querySelector(targetSelector);
if (!toggler) {
return;
}
toggler.onclick = function(event) {
event.preventDefault();
target.classList.toggle(className);
};
}
});
</script></nav></div><div class="container mainContainer docsContainer"><div class="wrapper"><div class="post"><header class="postHeader"><a class="edit-page-link button" href="https://github.com/facebook/react-native-website/blob/master/docs/communication-ios.md" target="_blank" rel="noreferrer noopener">Edit</a><h1 id="__docusaurus" class="postHeaderTitle">Communication between native and React Native</h1></header><article><div><span><p>In <a href="/docs/0.61/integration-with-existing-apps">Integrating with Existing Apps guide</a> and <a href="/docs/0.61/native-components-ios">Native UI Components guide</a> we learn how to embed React Native in a native component and vice versa. When we mix native and React Native components, we'll eventually find a need to communicate between these two worlds. Some ways to achieve that have been already mentioned in other guides. This article summarizes available techniques.</p>
<h2><a class="anchor" aria-hidden="true" id="introduction"></a><a href="#introduction" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Introduction</h2>
<p>React Native is inspired by React, so the basic idea of the information flow is similar. The flow in React is one-directional. We maintain a hierarchy of components, in which each component depends only on its parent and its own internal state. We do this with properties: data is passed from a parent to its children in a top-down manner. If an ancestor component relies on the state of its descendant, one should pass down a callback to be used by the descendant to update the ancestor.</p>
<p>The same concept applies to React Native. As long as we are building our application purely within the framework, we can drive our app with properties and callbacks. But, when we mix React Native and native components, we need some specific, cross-language mechanisms that would allow us to pass information between them.</p>
<h2><a class="anchor" aria-hidden="true" id="properties"></a><a href="#properties" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Properties</h2>
<p>Properties are the simplest way of cross-component communication. So we need a way to pass properties both from native to React Native, and from React Native to native.</p>
<h3><a class="anchor" aria-hidden="true" id="passing-properties-from-native-to-react-native"></a><a href="#passing-properties-from-native-to-react-native" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Passing properties from native to React Native</h3>
<p>In order to embed a React Native view in a native component, we use <code>RCTRootView</code>. <code>RCTRootView</code> is a <code>UIView</code> that holds a React Native app. It also provides an interface between native side and the hosted app.</p>
<p><code>RCTRootView</code> has an initializer that allows you to pass arbitrary properties down to the React Native app. The <code>initialProperties</code> parameter has to be an instance of <code>NSDictionary</code>. The dictionary is internally converted into a JSON object that the top-level JS component can reference.</p>
<pre><code class="hljs css language-objectivec"><span class="hljs-built_in">NSArray</span> *imageList = @[<span class="hljs-string">@"http://foo.com/bar1.png"</span>,
<span class="hljs-string">@"http://foo.com/bar2.png"</span>];
<span class="hljs-built_in">NSDictionary</span> *props = @{<span class="hljs-string">@"images"</span> : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:<span class="hljs-string">@"ImageBrowserApp"</span>
initialProperties:props];
</code></pre>
<pre><code class="hljs css language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> View<span class="token punctuation">,</span> Image <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-native'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">ImageBrowserApp</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
<span class="token function">renderImage</span><span class="token punctuation">(</span><span class="token parameter">imgURI</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">Image</span></span> <span class="token attr-name">source</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> uri<span class="token punctuation">:</span> imgURI <span class="token punctuation">}</span><span class="token punctuation">}</span></span> <span class="token punctuation">/></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">View</span></span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>images<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>renderImage<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">View</span></span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>RCTRootView</code> also provides a read-write property <code>appProperties</code>. After <code>appProperties</code> is set, the React Native app is re-rendered with new properties. The update is only performed when the new updated properties differ from the previous ones.</p>
<pre><code class="hljs css language-objectivec"><span class="hljs-built_in">NSArray</span> *imageList = @[<span class="hljs-string">@"http://foo.com/bar3.png"</span>,
<span class="hljs-string">@"http://foo.com/bar4.png"</span>];
rootView.appProperties = @{<span class="hljs-string">@"images"</span> : imageList};
</code></pre>
<p>It is fine to update properties anytime. However, updates have to be performed on the main thread. You use the getter on any thread.</p>
<blockquote>
<p><strong><em>Note:</em></strong> Currently, there is a known issue where setting appProperties during the bridge startup, the change can be lost. See <a href="https://github.com/facebook/react-native/issues/20115">https://github.com/facebook/react-native/issues/20115</a> for more information.</p>
</blockquote>
<p>There is no way to update only a few properties at a time. We suggest that you build it into your own wrapper instead.</p>
<blockquote>
<p><strong><em>Note:</em></strong> Currently, JS function <code>componentWillUpdateProps</code> of the top level RN component will not be called after a prop update. However, you can access the new props in <code>componentDidMount</code> function.</p>
</blockquote>
<h3><a class="anchor" aria-hidden="true" id="passing-properties-from-react-native-to-native"></a><a href="#passing-properties-from-react-native-to-native" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Passing properties from React Native to native</h3>
<p>The problem exposing properties of native components is covered in detail in <a href="/docs/0.61/native-components-ios#properties">this article</a>. In short, export properties with <code>RCT_CUSTOM_VIEW_PROPERTY</code> macro in your custom native component, then use them in React Native as if the component was an ordinary React Native component.</p>
<h3><a class="anchor" aria-hidden="true" id="limits-of-properties"></a><a href="#limits-of-properties" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Limits of properties</h3>
<p>The main drawback of cross-language properties is that they do not support callbacks, which would allow us to handle bottom-up data bindings. Imagine you have a small RN view that you want to be removed from the native parent view as a result of a JS action. There is no way to do that with props, as the information would need to go bottom-up.</p>
<p>Although we have a flavor of cross-language callbacks (<a href="/docs/0.61/native-modules-ios#callbacks">described here</a>), these callbacks are not always the thing we need. The main problem is that they are not intended to be passed as properties. Rather, this mechanism allows us to trigger a native action from JS, and handle the result of that action in JS.</p>
<h2><a class="anchor" aria-hidden="true" id="other-ways-of-cross-language-interaction-events-and-native-modules"></a><a href="#other-ways-of-cross-language-interaction-events-and-native-modules" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Other ways of cross-language interaction (events and native modules)</h2>
<p>As stated in the previous chapter, using properties comes with some limitations. Sometimes properties are not enough to drive the logic of our app and we need a solution that gives more flexibility. This chapter covers other communication techniques available in React Native. They can be used for internal communication (between JS and native layers in RN) as well as for external communication (between RN and the 'pure native' part of your app).</p>
<p>React Native enables you to perform cross-language function calls. You can execute custom native code from JS and vice versa. Unfortunately, depending on the side we are working on, we achieve the same goal in different ways. For native - we use events mechanism to schedule an execution of a handler function in JS, while for React Native we directly call methods exported by native modules.</p>
<h3><a class="anchor" aria-hidden="true" id="calling-react-native-functions-from-native-events"></a><a href="#calling-react-native-functions-from-native-events" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Calling React Native functions from native (events)</h3>
<p>Events are described in detail in <a href="/docs/0.61/native-components-ios#events">this article</a>. Note that using events gives us no guarantees about execution time, as the event is handled on a separate thread.</p>
<p>Events are powerful, because they allow us to change React Native components without needing a reference to them. However, there are some pitfalls that you can fall into while using them:</p>
<ul>
<li>As events can be sent from anywhere, they can introduce spaghetti-style dependencies into your project.</li>
<li>Events share namespace, which means that you may encounter some name collisions. Collisions will not be detected statically, which makes them hard to debug.</li>
<li>If you use several instances of the same React Native component and you want to distinguish them from the perspective of your event, you'll likely need to introduce identifiers and pass them along with events (you can use the native view's <code>reactTag</code> as an identifier).</li>
</ul>
<p>The common pattern we use when embedding native in React Native is to make the native component's RCTViewManager a delegate for the views, sending events back to JavaScript via the bridge. This keeps related event calls in one place.</p>
<h3><a class="anchor" aria-hidden="true" id="calling-native-functions-from-react-native-native-modules"></a><a href="#calling-native-functions-from-react-native-native-modules" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Calling native functions from React Native (native modules)</h3>
<p>Native modules are Objective-C classes that are available in JS. Typically one instance of each module is created per JS bridge. They can export arbitrary functions and constants to React Native. They have been covered in detail in <a href="/docs/0.61/native-modules-ios#content">this article</a>.</p>
<p>The fact that native modules are singletons limits the mechanism in the context of embedding. Let's say we have a React Native component embedded in a native view and we want to update the native, parent view. Using the native module mechanism, we would export a function that not only takes expected arguments, but also an identifier of the parent native view. The identifier would be used to retrieve a reference to the parent view to update. That said, we would need to keep a mapping from identifiers to native views in the module.</p>
<p>Although this solution is complex, it is used in <code>RCTUIManager</code>, which is an internal React Native class that manages all React Native views.</p>
<p>Native modules can also be used to expose existing native libraries to JS. The <a href="https://github.com/facebook/react-native/tree/master/Libraries/Geolocation">Geolocation library</a> is a living example of the idea.</p>
<blockquote>
<p><strong><em>Warning</em></strong>: All native modules share the same namespace. Watch out for name collisions when creating new ones.</p>
</blockquote>
<h2><a class="anchor" aria-hidden="true" id="layout-computation-flow"></a><a href="#layout-computation-flow" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Layout computation flow</h2>
<p>When integrating native and React Native, we also need a way to consolidate two different layout systems. This section covers common layout problems and provides a brief description of mechanisms to address them.</p>
<h3><a class="anchor" aria-hidden="true" id="layout-of-a-native-component-embedded-in-react-native"></a><a href="#layout-of-a-native-component-embedded-in-react-native" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Layout of a native component embedded in React Native</h3>
<p>This case is covered in <a href="/docs/0.61/native-components-ios#styles">this article</a>. To summarize, as all our native react views are subclasses of <code>UIView</code>, most style and size attributes will work like you would expect out of the box.</p>
<h3><a class="anchor" aria-hidden="true" id="layout-of-a-react-native-component-embedded-in-native"></a><a href="#layout-of-a-react-native-component-embedded-in-native" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Layout of a React Native component embedded in native</h3>
<h4><a class="anchor" aria-hidden="true" id="react-native-content-with-fixed-size"></a><a href="#react-native-content-with-fixed-size" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>React Native content with fixed size</h4>
<p>The simplest scenario is when we have a React Native app with a fixed size, which is known to the native side. In particular, a full-screen React Native view falls into this case. If we want a smaller root view, we can explicitly set RCTRootView's frame.</p>
<p>For instance, to make an RN app 200 (logical) pixels high, and the hosting view's width wide, we could do:</p>
<pre><code class="hljs css language-objectivec"><span class="hljs-comment">// SomeViewController.m</span>
- (<span class="hljs-keyword">void</span>)viewDidLoad
{
[...]
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:appName
initialProperties:props];
rootView.frame = <span class="hljs-built_in">CGRectMake</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">self</span>.view.width, <span class="hljs-number">200</span>);
[<span class="hljs-keyword">self</span>.view addSubview:rootView];
}
</code></pre>
<p>When we have a fixed size root view, we need to respect its bounds on the JS side. In other words, we need to ensure that the React Native content can be contained within the fixed-size root view. The easiest way to ensure this is to use flexbox layout. If you use absolute positioning, and React components are visible outside the root view's bounds, you'll get overlap with native views, causing some features to behave unexpectedly. For instance, 'TouchableHighlight' will not highlight your touches outside the root view's bounds.</p>
<p>It's totally fine to update root view's size dynamically by re-setting its frame property. React Native will take care of the content's layout.</p>
<h4><a class="anchor" aria-hidden="true" id="react-native-content-with-flexible-size"></a><a href="#react-native-content-with-flexible-size" aria-hidden="true" class="hash-link"><svg class="hash-link-icon" aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>React Native content with flexible size</h4>
<p>In some cases we'd like to render content of initially unknown size. Let's say the size will be defined dynamically in JS. We have two solutions to this problem.</p>
<ol>
<li>You can wrap your React Native view in a <code>ScrollView</code> component. This guarantees that your content will always be available and it won't overlap with native views.</li>
<li>React Native allows you to determine, in JS, the size of the RN app and provide it to the owner of the hosting <code>RCTRootView</code>. The owner is then responsible for re-laying out the subviews and keeping the UI consistent. We achieve this with <code>RCTRootView</code>'s flexibility modes.</li>
</ol>
<p><code>RCTRootView</code> supports 4 different size flexibility modes:</p>
<pre><code class="hljs css language-objectivec"><span class="hljs-comment">// RCTRootView.h</span>
<span class="hljs-keyword">typedef</span> <span class="hljs-built_in">NS_ENUM</span>(<span class="hljs-built_in">NSInteger</span>, RCTRootViewSizeFlexibility) {
RCTRootViewSizeFlexibilityNone = <span class="hljs-number">0</span>,
RCTRootViewSizeFlexibilityWidth,
RCTRootViewSizeFlexibilityHeight,
RCTRootViewSizeFlexibilityWidthAndHeight,
};
</code></pre>
<p><code>RCTRootViewSizeFlexibilityNone</code> is the default value, which makes a root view's size fixed (but it still can be updated with <code>setFrame:</code>). The other three modes allow us to track React Native content's size updates. For instance, setting mode to <code>RCTRootViewSizeFlexibilityHeight</code> will cause React Native to measure the content's height and pass that information back to <code>RCTRootView</code>'s delegate. An arbitrary action can be performed within the delegate, including setting the root view's frame, so the content fits. The delegate is called only when the size of the content has changed.</p>
<blockquote>
<p><strong><em>Warning:</em></strong> Making a dimension flexible in both JS and native leads to undefined behavior. For example - don't make a top-level React component's width flexible (with <code>flexbox</code>) while you're using <code>RCTRootViewSizeFlexibilityWidth</code> on the hosting <code>RCTRootView</code>.</p>
</blockquote>
<p>Let's look at an example.</p>
<pre><code class="hljs css language-objectivec"><span class="hljs-comment">// FlexibleSizeExampleView.m</span>
- (<span class="hljs-keyword">instancetype</span>)initWithFrame:(<span class="hljs-built_in">CGRect</span>)frame
{
[...]
_rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:<span class="hljs-string">@"FlexibilityExampleApp"</span>
initialProperties:@{}];
_rootView.delegate = <span class="hljs-keyword">self</span>;
_rootView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight;
_rootView.frame = <span class="hljs-built_in">CGRectMake</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">self</span>.frame.size.width, <span class="hljs-number">0</span>);
}
<span class="hljs-meta">#<span class="hljs-meta-keyword">pragma</span> mark - RCTRootViewDelegate</span>
- (<span class="hljs-keyword">void</span>)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView
{
<span class="hljs-built_in">CGRect</span> newFrame = rootView.frame;
newFrame.size = rootView.intrinsicContentSize;
rootView.frame = newFrame;
}
</code></pre>
<p>In the example we have a <code>FlexibleSizeExampleView</code> view that holds a root view. We create the root view, initialize it and set the delegate. The delegate will handle size updates. Then, we set the root view's size flexibility to <code>RCTRootViewSizeFlexibilityHeight</code>, which means that <code>rootViewDidChangeIntrinsicSize:</code> method will be called every time the React Native content changes its height. Finally, we set the root view's width and position. Note that we set there height as well, but it has no effect as we made the height RN-dependent.</p>
<p>You can checkout full source code of the example <a href="https://github.com/facebook/react-native/blob/master/RNTester/RNTester/NativeExampleViews/FlexibleSizeExampleView.m">here</a>.</p>
<p>It's fine to change root view's size flexibility mode dynamically. Changing flexibility mode of a root view will schedule a layout recalculation and the delegate <code>rootViewDidChangeIntrinsicSize:</code> method will be called once the content size is known.</p>
<blockquote>
<p><strong><em>Note:</em></strong> React Native layout calculation is performed on a separate thread, while native UI view updates are done on the main thread. This may cause temporary UI inconsistencies between native and React Native. This is a known problem and our team is working on synchronizing UI updates coming from different sources.</p>
</blockquote>
<blockquote>
<p><strong><em>Note:</em></strong> React Native does not perform any layout calculations until the root view becomes a subview of some other views. If you want to hide React Native view until its dimensions are known, add the root view as a subview and make it initially hidden (use <code>UIView</code>'s <code>hidden</code> property). Then change its visibility in the delegate method.</p>
</blockquote>
</span></div></article></div><div class="docs-prevnext"><a class="docs-prev button" href="/docs/0.61/running-on-simulator-ios"><span class="arrow-prev">← </span><span>Running On Simulator</span></a><a class="docs-next button" href="/docs/0.61/app-extensions"><span>App Extensions</span><span class="arrow-next"> →</span></a></div></div></div><nav class="onPageNav"><ul class="toc-headings"><li><a href="#introduction">Introduction</a></li><li><a href="#properties">Properties</a><ul class="toc-headings"><li><a href="#passing-properties-from-native-to-react-native">Passing properties from native to React Native</a></li><li><a href="#passing-properties-from-react-native-to-native">Passing properties from React Native to native</a></li><li><a href="#limits-of-properties">Limits of properties</a></li></ul></li><li><a href="#other-ways-of-cross-language-interaction-events-and-native-modules">Other ways of cross-language interaction (events and native modules)</a><ul class="toc-headings"><li><a href="#calling-react-native-functions-from-native-events">Calling React Native functions from native (events)</a></li><li><a href="#calling-native-functions-from-react-native-native-modules">Calling native functions from React Native (native modules)</a></li></ul></li><li><a href="#layout-computation-flow">Layout computation flow</a><ul class="toc-headings"><li><a href="#layout-of-a-native-component-embedded-in-react-native">Layout of a native component embedded in React Native</a></li><li><a href="#layout-of-a-react-native-component-embedded-in-native">Layout of a React Native component embedded in native</a></li></ul></li></ul></nav></div><footer class="nav-footer" id="footer"><section class="sitemap"><div><h5>Docs</h5><a href="/docs/getting-started">Getting Started</a><a href="/docs/tutorial">Tutorial</a><a href="/docs/components-and-apis">Components and APIs</a><a href="/docs/more-resources">More Resources</a></div><div><h5>Community</h5><a href="/help">The React Native Community</a><a href="/showcase">Who's using React Native?</a><a href="https://stackoverflow.com/questions/tagged/react-native" target="_blank">Ask Questions on Stack Overflow</a><a href="https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md">Contributor Guide</a><a href="https://dev.to/t/reactnative" target="_blank">DEV Community</a></div><div><h5>More Resources</h5><a href="/blog">Blog</a><a href="https://twitter.com/reactnative" target="_blank">Twitter</a><a href="https://github.com/facebook/react-native" target="_blank">GitHub</a><a href="https://reactjs.org" target="_blank">React</a></div></section><a href="https://code.facebook.com/projects/" target="_blank" class="fbOpenSource"><img src="/img/oss_logo.png" alt="Facebook Open Source" width="170" height="45"/></a><section class="copyright">Copyright © 2020 Facebook Inc.</section></footer></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>window.fbAsyncInit = function() {FB.init({appId:'1677033832619985',xfbml:true,version:'v2.7'});};(function(d, s, id){var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) {return;}js = d.createElement(s); js.id = id;js.src = '//connect.facebook.net/en_US/sdk.js';fjs.parentNode.insertBefore(js, fjs);}(document, 'script','facebook-jssdk'));
</script><script>window.twttr=(function(d,s, id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return t;js=d.createElement(s);js.id=id;js.src='https://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js, fjs);t._e = [];t.ready = function(f) {t._e.push(f);};return t;}(document, 'script', 'twitter-wjs'));</script><script>
document.addEventListener('keyup', function(e) {
if (e.target !== document.body) {
return;
}
// keyCode for '/' (slash)
if (e.keyCode === 191) {
const search = document.getElementById('search_input_react');
search && search.focus();
}
});
</script><script>
var search = docsearch({
apiKey: '2c98749b4a1e588efec53b2acec13025',
indexName: 'react-native-versions',
inputSelector: '#search_input_react',
algoliaOptions: {"facetFilters":["tags:0.61"],"hitsPerPage":5}
});
</script></body></html>