<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Elliot Hesp on Medium]]></title>
        <description><![CDATA[Stories by Elliot Hesp on Medium]]></description>
        <link>https://medium.com/@elliothesp?source=rss-e023bdd499ec------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*7UrjfelU9cnZVH2KxF5SPQ.jpeg</url>
            <title>Stories by Elliot Hesp on Medium</title>
            <link>https://medium.com/@elliothesp?source=rss-e023bdd499ec------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:29:03 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@elliothesp/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Detecting Android soft navigation keys in React Native]]></title>
            <link>https://medium.com/@elliothesp/detecting-android-soft-navigation-keys-in-react-native-30163abd7113?source=rss-e023bdd499ec------2</link>
            <guid isPermaLink="false">https://medium.com/p/30163abd7113</guid>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-navigation]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[react-native]]></category>
            <dc:creator><![CDATA[Elliot Hesp]]></dc:creator>
            <pubDate>Tue, 17 Oct 2017 14:54:26 GMT</pubDate>
            <atom:updated>2017-10-17T15:10:00.601Z</atom:updated>
            <content:encoded><![CDATA[<p>Android devices rarely come with hard bottom navigation keys these days. Whilst you don’t really need to worry about them (by default they’re just black), it is possible to integrate them into the theme of your app, creating a truly immersive experience.</p><p>The app below uses <a href="https://www.npmjs.com/package/react-native-material-bottom-navigation">react-native-material-bottom-navigation</a> to create the Bottom Navigation tabs in our Android app with soft navigation keys:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/524/1*lH2-ZFFXf8XX_3Bz1ApKEg.png" /></figure><p>Following the steps in “<a href="https://www.npmjs.com/package/react-native-material-bottom-navigation#behind-the-navigation-bar">Behind the navigation bar</a>”, we can see how to ‘remove’ (make transparent/translucent) the bottom navigation bar from our app:</p><p><strong>Step 1.</strong> In order to make the System Navigation translucent, you have to add this to android/app/src/main/res/values/styles.xml:</p><pre><em>&lt;!-- Customize your theme here. --&gt;</em></pre><pre>&lt;item <strong>name</strong>=&quot;android:navigationBarColor&quot;&gt;<br>  @android:color/transparent<br>&lt;/item&gt;<br>&lt;item <strong>name</strong>=&quot;android:windowTranslucentNavigation&quot;&gt;<br>  true<br>&lt;/item&gt;</pre><p><strong>Step 2.</strong> The System Navigation has a height of 48dp. The Bottom Navigation should be 56dp tall. This makes a total height of 104. Use innerStyle to push the tabs above the System Navigation without pushing the whole Bottom Navigation above it.</p><pre>&lt;BottomNavigation<br>  <strong>style</strong>={{ height<strong>:</strong> 104 }}<br>  <strong>innerStyle</strong>={{ paddingBottom<strong>:</strong> 48 }}<br>&gt;</pre><p><strong>Step 3.</strong> You’re done!</p><h3>What if my device has hard navigation keys?!</h3><p>In this case, you’re going to be creating a height and applying padding to a space which doesn’t actually exist, leaving a 48hp high block bar below your navigation. The simple solution is to only apply the styles described in step 2 above if the device has soft keys.</p><p>The only real way to detect this is hooking to the Android SDK. This is actually super easy to do with React Native. We’re going to provide some constants back which JavaScript can read.</p><h3>Creating the native module</h3><p>In Android Studio, go ahead and open the following file:android/app/src/main/java/com/&lt;&lt; yourappname &gt;&gt;/MainApplication.java</p><p>Within our getPackages method, we’ll export a new package (which is automatically imported as we’re in the same directory where we’ll create it):</p><pre>@Override<br>protected List&lt;ReactPackage&gt; getPackages() {<br>    return Arrays.&lt;ReactPackage&gt;<em>asList</em>(<br>            new MainReactPackage(),<br>            new MyAppPackage()</pre><p>Next create the package in: android/app/src/main/java/com/&lt;&lt; yourappname &gt;&gt;/MyAppPackage.java</p><p>Our package will export a module with the current React context (which allows us to hook into React Native stuff such as the current Android activity):</p><pre>package com.yourappname;<br><br>import com.facebook.react.ReactPackage;<br>import com.facebook.react.bridge.NativeModule;<br>import com.facebook.react.bridge.ReactApplicationContext;<br>import com.facebook.react.uimanager.ViewManager;<br><br>import java.util.ArrayList;<br>import java.util.Collections;<br>import java.util.List;<br><br><br>public class MyAppPackage implements ReactPackage {<br><br>    public MyAppPackage() {<br>    }<br><br>    @Override<br>    public List&lt;NativeModule&gt;<br>    createNativeModules(ReactApplicationContext reactContext) {<br>        List&lt;NativeModule&gt; modules = new ArrayList&lt;NativeModule&gt;();<br>        modules.add(new MyAppModule(reactContext));<br>        return modules;<br>    }<br><br>    @Override<br>    public List&lt;ViewManager&gt;<br>    createViewManagers(ReactApplicationContext reactApplicationContext) {<br>        return Collections.<em>emptyList</em>();<br>    }<br>}</pre><p>MyAppModule is another java file which is automatically read from the current working directory. Our own package is now just exporting it for use.</p><p>Now go ahead and create the MyAppModule file: android/app/src/main/java/com/&lt;&lt; yourappname &gt;&gt;/MyAppModule.java</p><p>This file is the one React Native will pick up when we access our module from the JavaScript world. We can provide a getConstants method which returns a static type which can be read. In our case, we simply want a true/false value on whether the device has soft keys.</p><h3>MyAppModule.java</h3><p>First up we need to extend the a base class to provide us with the ability to create a module:</p><pre>package com.yourappname;</pre><pre>import com.facebook.react.bridge.ReactApplicationContext;<br>import com.facebook.react.bridge.ReactContextBaseJavaModule;</pre><pre>public class MyAppModule extends ReactContextBaseJavaModule {</pre><p>We need to now call the “constructor” (same as you would in a React class) and pass the React context to the ReactContextBaseJavaModule class using super:</p><pre>public MyAppModule(ReactApplicationContext reactContext) {<br>    super(reactContext);<br>}</pre><p>The next step provides React Native to access the module by name via NativeModules in JavaScript land. Lets go ahead and name our module:</p><pre>@Override<br>public String getName() {<br>    return &quot;MyAppModule&quot;;<br>}</pre><p>We can now create our getConstants method, which will return whether we’ve got soft keys or not:</p><pre>@Override<br>public Map&lt;String, Object&gt; getConstants() {<br>    Map&lt;String, Object&gt; constants = new HashMap&lt;&gt;();<br><br>    constants.put(&quot;has_soft_keys&quot;, hasSoftKeys());<br><br>    return constants;<br>}</pre><p>Here we return a HashMap. Think of it as an Object with key/value pairs. Our key is has_soft_keys and the value is the result of calling the function hasSoftKeys which we’ll create now:</p><pre>private boolean hasSoftKeys() {<br>    boolean hasSoftwareKeys;<br><br>    Activity activity = getCurrentActivity();<br><br>    if (activity == null) {<br>        return true;<br>    }<br><br>    WindowManager window = getCurrentActivity().getWindowManager();<br><br>    if(window != null &amp;&amp; Build.VERSION.<em>SDK_INT </em>&gt;= Build.VERSION_CODES.<em>JELLY_BEAN_MR1</em>){<br>        Display d = getCurrentActivity().getWindowManager().getDefaultDisplay();<br><br>        DisplayMetrics realDisplayMetrics = new DisplayMetrics();<br>        d.getRealMetrics(realDisplayMetrics);<br><br>        int realHeight = realDisplayMetrics.heightPixels;<br>        int realWidth = realDisplayMetrics.widthPixels;<br><br>        DisplayMetrics displayMetrics = new DisplayMetrics();<br>        d.getMetrics(displayMetrics);<br><br>        int displayHeight = displayMetrics.heightPixels;<br>        int displayWidth = displayMetrics.widthPixels;<br><br>        hasSoftwareKeys =  (realWidth - displayWidth) &gt; 0 || (realHeight - displayHeight) &gt; 0;<br>    } else {<br>        boolean hasMenuKey = ViewConfiguration.<em>get</em>(mContext).hasPermanentMenuKey();<br>        boolean hasBackKey = KeyCharacterMap.<em>deviceHasKey</em>(KeyEvent.<em>KEYCODE_BACK</em>);<br><br>        hasSoftwareKeys = !hasMenuKey &amp;&amp; !hasBackKey;<br>    }<br><br>    return hasSoftwareKeys;<br>}</pre><p>Don’t worry too much about what’s happening here-it’s just detecting whether we’re able to access certain APIs depending on the Android version and checks whether the soft keys are there using various checks.</p><p>Don’t forget to import the required classes at the top:</p><pre>import java.util.HashMap;<br>import java.util.Map;</pre><pre>import android.os.Build;<br>import android.util.DisplayMetrics;<br>import android.view.Display;<br>import android.view.KeyCharacterMap;<br>import android.view.KeyEvent;<br>import android.view.ViewConfiguration;<br>import android.view.WindowManager;</pre><h3>Accessing our native module</h3><p>Once you’ve recompiled your app, React Native provides access to our native modules using the NativeModules API. Lets go ahead and grab out the constants we’ve just created, and conditionally apply these to our component styles:</p><pre>import { NativeModules } from &#39;react-native&#39;;<br>const hasSoftKeys = !!NativeModules.MyAppModule.has_soft_keys;</pre><pre>....</pre><pre>&lt;BottomNavigation<br>  <strong>style</strong>={{ hasSoftKeys ? { height<strong>:</strong> 104 } : null }}<br>  <strong>innerStyle</strong>={{ hasSoftKeys ? { paddingBottom<strong>:</strong> 48 } : null }}<br>&gt;</pre><p>Sorted! We how will only apply the height and padding if there is soft keys on the device, otherwise it’ll sit the BottomNavigation directly at the bottom of the device screen.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=30163abd7113" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting started with Cloud Firestore on React Native]]></title>
            <link>https://medium.com/invertase/getting-started-with-cloud-firestore-on-react-native-b338fb6525b9?source=rss-e023bdd499ec------2</link>
            <guid isPermaLink="false">https://medium.com/p/b338fb6525b9</guid>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[firebase]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Elliot Hesp]]></dc:creator>
            <pubDate>Tue, 10 Oct 2017 15:42:10 GMT</pubDate>
            <atom:updated>2017-10-17T15:10:58.621Z</atom:updated>
            <content:encoded><![CDATA[<p>A week ago, Firebase announced <a href="https://firebase.googleblog.com/2017/10/introducing-cloud-firestore.html">Cloud Firestore</a>, an awesome NoSQL document database that complements the existing Realtime Database. <a href="https://github.com/invertase/react-native-firebase">React Native Firebase</a> (RNFirebase) is proud to announce support for both Android &amp; iOS on React Native.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*3bvCV40S4uMI5X581kXbHg.jpeg" /><figcaption>Firebase Cloud Firestore + React Native Firebase</figcaption></figure><p>To get started, we’ve made a <a href="http://invertase.link/starter">starter app</a> which is all setup and ready to go — simply clone/download it and follow the instructions in the README!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/523/1*9oo8gsUHFw2bcrC0rYkCiQ.png" /><figcaption>The basic todo app — which we’ll create by the end of this article.</figcaption></figure><h3>Building a TODO app with Cloud Firestore &amp; RNFirebase</h3><p>Lets go ahead and build a simple TODO app with Cloud Firestore &amp; RNFirebase. Assuming you’ve used the <a href="http://invertase.link/starter">starter app</a> mentioned above or added react-native-firebase manually to an existing project (the docs are <a href="https://invertase.io/react-native-firebase/#/initial-setup">here</a>), we can get started!</p><p>Create a new file Todos.js in the root of your React Native project and point your index.android.js / index.ios.js files to load it:</p><pre>import { AppRegistry } from &#39;react-native&#39;;<br>import Todos from &#39;./Todos&#39;;</pre><pre>AppRegistry.registerComponent(&#39;RNFirebaseStarter&#39;, () =&gt; Todos);</pre><p>Next setup a basic React class in Todos.js :</p><pre>import React from &#39;react&#39;;</pre><pre>class Todos extends React.Component {<br>  render() {<br>    return null;<br>  }<br>}</pre><pre>export default Todos;</pre><h3>Creating your Cloud Firestore data structure</h3><p>Cloud Firestore allows documents (objects of data) to be stored in collections (containers for your documents). Our TODO app will simply hold a list of todo documents within a single “todos” collection. Each document contains data specific to that todo — in our case title and complete properties.</p><p>The first step is to create a reference to the collection, which can be used throughout our component to query it. We’ll import react-native-firebase and create this reference in our component constructor.</p><pre>import React from &#39;react&#39;;<br>import firebase from &#39;react-native-firebase&#39;;</pre><pre>class Todos extends React.Component {<br>  constructor() {<br>    super();<br>    this.ref = firebase.firestore().collection(&#39;todos&#39;);<br>  }<br>...</pre><h3>Building the UI</h3><p><em>For blog readability, we’ll add the styles in-line however you should use </em><a href="https://facebook.github.io/react-native/docs/stylesheet.html"><em>StyleSheet</em></a><em> for production apps.</em></p><blockquote>The screenshots are from an Android emulator, however the following will also work in an iOS environment!</blockquote><p>The UI will be simple: a scrollable list of todos, along with a text input to add new ones. Lets go ahead and build out our render method:</p><pre>import { ScrollView, View, Text, TextInput, Button } from &#39;react-native&#39;;<br>...</pre><pre>render() {<br>  return (<br>    &lt;<strong>View</strong>&gt;<br>      &lt;<strong>ScrollView</strong>&gt;<br>        &lt;<strong>Text</strong>&gt;<strong>List of TODOs</strong>&lt;/<strong>Text</strong>&gt;<br>      &lt;/<strong>ScrollView</strong>&gt;<br>      &lt;<strong>TextInput<br>        </strong>placeholder={&#39;Add TODO&#39;}<br>      /&gt;<br>      &lt;<strong>Button<br>        </strong>title={&#39;Add TODO&#39;}<br>        disabled={true}<br>        onPress={() =&gt; {}}<br>      /&gt;<br>    &lt;/<strong>View</strong>&gt;<br>  );<br>}</pre><p>You should now see a dummy scrollview, a text input and a button which does nothing… something similar to the following:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/537/1*Sl6H4QUoHeArYM5lBTL_Zw.png" /></figure><p>We now need to hook the text input up to our local state so we can send the value to Cloud Firestore when the button is pressed.</p><p>Add the constructor default state:</p><pre>constructor() {<br>    super();<br>    this.ref = firebase.firestore().collection(&#39;todos&#39;);<br>    this.state = {<br>        textInput: &#39;&#39;,<br>    };<br>}</pre><p>Add the method updateTextInput to update component state when the TextInput value updates:</p><pre>updateTextInput(<em>value</em>) {<br>    this.setState({ textInput: <em>value </em>});<br>}</pre><p>Hook up the TextInput to state and trigger a state update on text change:</p><pre>&lt;<strong>TextInput<br>    </strong>placeholder={&#39;Add TODO&#39;}<br>    value={this.state.textInput}<br>    onChangeText={(<em>text</em>) =&gt; this.updateTextInput(<em>text</em>)}<br>/&gt;</pre><p>Change the buttons <strong>disabled</strong> state based on the length of the text input value:</p><pre>&lt;<strong>Button<br>    </strong>title={&#39;Add TODO&#39;}<br>    disabled={!this.state.textInput.length}<br>    onPress={() =&gt; {}}<br>/&gt;</pre><p>Your app should now respond to text changes, with the value reflecting local state and your buttons <strong>disabled</strong> state:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/537/1*fWQT5zQN0-w0B6nbsMimHw.png" /></figure><h3>Adding a new Document</h3><p>To add a new document to the collection, we can call the add method on the collection reference. Lets hook our button up and add the todo!</p><p>Add a addTodo method:</p><pre>addTodo() {<br>  this.ref.add({<br>    title: this.state.textInput,<br>    complete: false,<br>  });</pre><pre>  this.setState({<br>    textInput: &#39;&#39;,<br>  });<br>}</pre><p>Let the button trigger the method:</p><pre>&lt;<strong>Button<br>    </strong>title={&#39;Add TODO&#39;}<br>    disabled={!this.state.textInput.length}<br>    onPress={() =&gt; this.addTodo()}<br>/&gt;</pre><p>When our button is pressed, the new todo is sent to Cloud Firestore and added to the collection. We then reset the <strong>textInput</strong> component state. The add method is asynchronous and returns the <a href="https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference">DocumentReference</a> from a Promise if required.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-u8qxEIMmu69zMgBNlHZkw.png" /><figcaption>Our newly added todo document on the Cloud Firestore console.</figcaption></figure><p><em>Make sure you have permission to add data to the collection on your Rules page!</em></p><h3>Subscribing to collection updates</h3><p>Even though we’re populating the collection, we still need to display the documents on our app. Cloud Firestore provides two methods; get() queries the collection once and onSnapshot() which gives updates in realtime when a document changes. For our TODO app, we’ll want realtime results. Lets go ahead and setup some more component state to handle the data.</p><p>Add a loading state and todos state to the component:</p><pre>constructor() {<br>    super();<br>    this.ref = firebase.firestore().collection(&#39;todos&#39;);<br>    this.unsubscribe = null;</pre><pre>    this.state = {<br>        textInput: &#39;&#39;,<br>        loading: true,<br>        todos: [],<br>    };<br>}</pre><p><em>We need a </em><em>loading state to indicate to the user that the first connection to Cloud Firestore hasn’t yet completed. We also added a </em><em>unsubscribe class property which we’ll see the usage of next.</em></p><p>Subscribe to collection updates on component mount:</p><pre>componentDidMount() {<br>    this.unsubscribe = this.ref.onSnapshot(this.onCollectionUpdate) <br>}<br><br>componentWillUnmount() {<br>    this.unsubscribe();<br>}</pre><p>onSnapshot returns an “unsubscriber” function to allow us to stop receiving updates, which we call when the component is about to unmount.</p><p>Implement the onCollectionUpdate method:</p><pre>onCollectionUpdate = (querySnapshot) =&gt; {</pre><pre>}</pre><p><em>Note: an arrow function (</em><em>=&gt;) is used here to ensure the </em><em>onCollectionUpdate method is bound to the </em><strong><em>Todos</em></strong><em> component scope.</em></p><p>Iterate over the documents and populate state:</p><pre>onCollectionUpdate = (querySnapshot) =&gt; {<br>  const todos = [];</pre><pre>  querySnapshot.forEach((doc) =&gt; {<br>    const { title, complete } = doc.data();</pre><pre>    todos.push({<br>      key: doc.id,<br>      doc, // DocumentSnapshot<br>      title,<br>      complete,<br>    });<br>  });</pre><pre>  this.setState({ <br>    todos,<br>    loading: false,<br> });<br>}</pre><p>We use the snapshot forEach method to iterate over each DocumentSnapshot in the order they are stored on Cloud Firestore, and grab the documents unique ID (.id) and data (.data()). We also store the DocumentSnapshot in state to access it directly later.</p><p>Every time a document is created, deleted or modified on the collection, this method will trigger and update component state.</p><h3>Rendering the todos</h3><p>Now we have the todos loading into state, we need to render them. A ScrollView is not practical here as a list of TODOs with many items will cause performance issues when updating. Instead we’ll use a <a href="https://facebook.github.io/react-native/docs/flatlist.html">FlatList</a>.</p><p>Handle loading state:</p><pre>render() {<br>  if (this.state.loading) {<br>    return null; // or render a loading icon<br>  }</pre><p>Render the todos in a FlatList using the todos state:</p><pre>import { <strong>FlatList</strong>, Button, View, Text, TextInput } from &#39;react-native&#39;;</pre><pre>import Todo from &#39;./Todo&#39;; // we&#39;ll create this next<br>...</pre><pre>render() {<br>  if (this.state.loading) {<br>    return null; // or render a loading icon<br>  }</pre><pre>  return (<br>    &lt;<strong>View </strong>style={{ flex: 1 }}&gt;<br>        &lt;<strong>FlatList<br>          </strong>data={this.state.todos}<br>          renderItem={({ <em>item </em>}) =&gt; &lt;<strong>Todo {...</strong><em>item</em><strong>}</strong> /&gt;}<br>        /&gt;<br>        &lt;<strong>TextInput<br>            </strong>placeholder={&#39;Add TODO&#39;}<br>            value={this.state.textInput}<br>            onChangeText={(<em>text</em>) =&gt; this.updateTextInput(<em>text</em>)}<br>        /&gt;<br>        &lt;<strong>Button<br>            </strong>title={&#39;Add TODO&#39;}<br>            disabled={!this.state.textInput.length}<br>            onPress={() =&gt; this.addTodo()}<br>        /&gt;<br>    &lt;/<strong>View</strong>&gt;<br>  );<br>}</pre><p>You may notice that we’ve got a Todo component rendering for each item. Below we’ll quickly create this as a PureComponent. This will provide huge performance boosts in our app as each row will only re-render when a prop (title or complete) changes.</p><p>Create a <strong>Todo.js</strong> file in the root of your project:</p><pre>import React from &#39;react&#39;;<br>import { <strong>TouchableHighlight, View, Text } from &#39;react-native&#39;;</strong></pre><pre>export default class <strong>Todo</strong> extends React.PureComponent {</pre><pre>    // toggle a todo as completed or not via update()<br>    toggleComplete() {<br>        this.props.doc.ref.update({<br>            complete: !this.props.complete,<br>        });<br>    }<br><br>    render() {<br>        return (<br>          &lt;<strong>TouchableHighlight<br>            </strong>onPress={() =&gt; this.toggleComplete()}<br>          &gt;<br>              &lt;<strong>View </strong>style={{ flex: 1, height: 48, flexDirection: &#39;row&#39;, alignItems: &#39;center&#39; }}&gt;<br>                  &lt;<strong>View </strong>style={{ flex: 8 }}&gt;<br>                      &lt;<strong>Text</strong>&gt;{this.props.title}&lt;/<strong>Text</strong>&gt;<br>                  &lt;/<strong>View</strong>&gt;<br>                  &lt;<strong>View </strong>style={{ flex: 2 }}&gt;<br>                      {this.props.complete &amp;&amp; (<br>                          &lt;<strong>Text</strong>&gt;<strong>COMPLETE</strong>&lt;/<strong>Text</strong>&gt;<br>                      )}<br>                  &lt;/<strong>View</strong>&gt;<br>              &lt;/<strong>View</strong>&gt;<br>          &lt;/<strong>TouchableHighlight</strong>&gt;<br>        );<br>    }<br>}</pre><p>This component just renders out the title and whether the todo document is completed or not. It’s wrapped in a TouchableHighlight component, allowing us to make it a touchable row. When the row is pressed, we can grab the ref (DocumentReference) directly from the doc prop (DocumentSnapshot) and update it using the update method (which again is asynchronous if you wish to handle errors).</p><p>We can now toggle the todos completed state and not worry about local state as our onSnapshot subscription propagates the updates from Cloud Firestore back to our component in real time, awesome huh?!</p><p>You should see the following — realtime interaction with Cloud Firestore!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/523/1*SHslv9sBXSXtdjSv8XNj5w.png" /></figure><p>This is just a taster of what react-native-firebase and Cloud Firestore can do for your React Native applications. If you want to keep up to date, you can follow us here, on <a href="http://invertase.link/twitter">Twitter</a>, over at the main <a href="http://invertase.link/github">GitHub repo</a> or chat with us on <a href="https://discord.gg/t6bdqMs">Discord</a>.</p><p><strong><em>Thanks for reading! If you liked this story, please click the 👏 below so other people will see it on Medium (it really helps, otherwise it doesn’t get into others’ feeds). Sharing on Facebook and re-tweeting is appreciated too!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b338fb6525b9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/invertase/getting-started-with-cloud-firestore-on-react-native-b338fb6525b9">Getting started with Cloud Firestore on React Native</a> was originally published in <a href="https://medium.com/invertase">Invertase</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>