Get your team started on a custom learning journey today!
Our Boulder, CO-based learning experts are ready to help!
Get your team started on a custom learning journey today!
Our Boulder, CO-based learning experts are ready to help!
Follow us on LinkedIn for our latest data and tips!
In this tutorial I’ll be showing you how to create a very Twitter Clone using React and Firebase. MobX will be used as the data store for Firebase data. Here’s what the final output is going to look like:
In order to not bog us down in Firebase setup, this tutorial will assume that you already have an existing Firebase project created in the Firebase Console. If not, go ahead and create one. Once you have a project, go to the database section and under the rules tab add the following:
{ "rules": { ".read": true, ".write": true } }
This sets read and write permissions of your database to public. This means you don’t need to authenticate later on in order to gain access the database. This is good for quickly getting started with something, but not for production apps. Be sure to change this later!
Clone the create-react-app-mobx project. This allows you to easily create a React Project which has already the MobX toolset built into it (the original create-react-app doesn’t support all MobX features yet).
git clone https://github.com/mobxjs/create-react-app-mobx.git react-firebase-mobx-twitter-clone
Next, open your package.json
file and add the following:
"mobx-firebase-store": "^1.0.3", "react-timeago": "^3.2.0", "chance": "^1.0.6", "slugify": "^1.1.0", "twitter-text": "^1.14.3"
Here’s a breakdown of what each package does:
Execute npm install
to install all the packages. Once that’s done, you can run npm start
to serve the project for development. You can access https://localhost:3000
on your browser to view the project.
Before moving on, delete everything inside the src
folder of the project. By default it contains a demo project that uses MobX to implement a counter app. We don’t really need those so you can go ahead and delete them.
Create an index.js
file. This is where you supply your Firebase database URL and render the main app component which you’ll be creating later:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; const config = { databaseURL: 'https://{YOUR_FIREBASE_PROJECT_NAME}.firebaseio.com', }; ReactDOM.render(, document.getElementById('root') );
Next, create an App.js
file. This is where you import the TweetList
component we’ll build that serves as the component that the user will interact with, and the TweetStore
store which contains the code for connecting, and saving/reading data from Firebase.
import React, { Component } from 'react'; import TweetList from './TweetList'; import TweetStore from './TweetStore'; import './index.css'; class App extends Component { componentWillMount() { this.store = new TweetStore(this.props.config); //create a new instance of the store by passingin the Firebase config } render() { return (); } } export default App;MobX-Firebase Twitter Clone
Now we’ll create the TweetList.js
file. At the very top, import all the libraries and components that you need. You’ll see how each of these will be used later so we won’t cover what each one does here.
import React, { Component } from 'react'; import { observer } from 'mobx-react'; import { createAutoSubscriber } from 'firebase-nest'; import Chance from 'chance'; import slugify from 'slugify'; import TimeAgo from 'react-timeago' import twitter_text from 'twitter-text'; const tweet_limit = 140; var ch = new Chance();
Next, create the Tweetlist component. Initialize the state as well as the functions inside the constructor
.
class TweetList extends Component { constructor(props) { super(props); this.state = { tweet: '', //the user's tweet text username: slugify(ch.name()), loading: false, //whether the Firebase data is currently loading or not remaining: tweet_limit //number of characters allowed for each tweet }; this.updateText = this.updateText.bind(this); this.submitTweet = this.submitTweet.bind(this); } ... }
The render()
method uses the getTweets()
method from the store. You’ll be creating this later, for now know that everytime someone makes a change to your Firebase database, the component gets re-rendered. If the Firebase data becomes available, the textarea for entering the tweet and the list of tweets gets rendered.
render() { const tweets = this.props.store.getTweets(); if (!tweets) { returnLoading tweets...} return (); }{this.state.username}{this.state.remaining}{tweets.keys().reverse().map(messageKey => this.renderTweet(messageKey, tweets.get(messageKey)))}
Here’s the function for rendering each tweet:
renderTweet(key, tweet) { return (); } @{tweet.username} -
The function for updating the state of the current tweet text and remaining count:
updateText(evt) { let tweet = evt.target.value let remaining = tweet_limit - twitter_text.getTweetLength(tweet); this.setState({ tweet, remaining }); }
The function for saving the tweet in Firebase:
submitTweet() { this.props.store.createTweet({ username: this.state.username, timestamp: new Date().getTime(), text: this.state.tweet }); this.setState({ tweet: '', remaining: tweet_limit }); }
Next, you need to define the getSubs()
and subscribeSubs()
function. The naming is relevant because the Firebase-nest library rely on these two functions. getSubs()
returns the array of subscriptions while subscribeSubs()
performs the subscription and returns the function for unsubscribing from the Firebase data.
getSubs(props, state) { return props.store.allTweetsSubs(); } subscribeSubs (subs, props, state) { return props.store.subscribeSubs(subs); }
Finally, you use the createAutoSubscriber()
function to subscribe and observe to Firebase data. This function uses the getSubs()
and subscribeSubs()
functions that you defined earlier in order to subscribe to Firebase data and propagate the changes in the store. It will then return the function that requires a Reactive component to be passed in. We can turn our component into a Reactive one by wrapping it in MobX’s observer()
function. This ensures that any data that is used for rendering the component forces a re-rendering when it’s updated. If you don’t set your component as an observer, it won’t re-render when the current user or someone else posts a new tweet.
export default createAutoSubscriber()(observer(TweetList));
We shall now create out Mobx store. Create a TweetStore.js
file. This serves as the store for the TweetList
component. It contains the methods for saving and fetching data from Firebase.
Start by importing firebase
and mobx-firebase-store
. firebase
is the official Firebase JavaScript library for working with Firebase. This allows you to connect to Firebase. The mobx-firebase-store
library provides a bridge between the Firebase library and the MobX library. It allows you to subscribe to Firebase data through the use of firebase-nest
subscriptions. This makes the data flow into MobX’s observable maps.
import Firebase from 'firebase'; import MobxFirebaseStore from 'mobx-firebase-store';
Define the property in which the array of tweets are stored:
const tweets_subkey = 'tweets';
Here’s what it looks like in the Firebase console:
Create the store. Inside the constructor
, connect to Firebase and create the store. MobXFirebaseStore
accepts a reference to a Firebase database as its argument. Right below that, call super(store.fb)
to make the store available inside the class via this
.
export default class TweetStore extends MobxFirebaseStore { constructor(config) { const fbApp = Firebase.initializeApp(config); const store = new MobxFirebaseStore(Firebase.database(fbApp).ref()); super(store.fb); } ... }
allTweetsSubs()
as you’ve known earlier, returns an array of subscriptions. In this case you only want to subscribe to a single subkey (tweets
) and you want its data to be returned as a list (asList: true
). Basically, it’s used to specify the subkey in your Firebase database that you want to subscribe to.
allTweetsSubs() { return [{ subKey: tweets_subkey, asList: true }]; }
createTweet()
uses Firebase’s push
method to push the tweet
object into the array. This creates a new item in the tweets
array in Firebase which then triggers the subscriber to update the list of tweets for all the connected clients.
createTweet(tweet) { this.fb.child(tweets_subkey).push(tweet); }
getTweets()
returns the collection of tweets:
getTweets() { return this.getData(tweets_subkey); }
resolveFirebaseQuery()
is used for customizing the query used for fetching Firebase data. Here, the results are ordered according to their timestamp
and only the 10 most recent tweets are being fetched. That said, Firebase still returns the records in ascending order that’s why you had to call reverse()
on the TweetList
component earlier to reverse the ordering.
resolveFirebaseQuery(sub) { return this.fb.child(tweets_subkey).orderByChild('timestamp').limitToLast(10); }
Open the public/index.html
file and add the following inside the <head>
:
This uses picnic.css to add some default styling to make the project look good.
Next, create a src/index.css
file and add the following:
body { margin: 0; padding: 0; font-family: sans-serif; } .tweets { margin-top: 30px; } .tweet { padding: 20px; }
That’s it! In this tutorial you’ve learned how to use MobX to act as a data store for your Firebase data. As you have seen, using Firebase with MobX doesn’t completely change the way you interact with Firebase so you can still use your existing knowledge of the Firebase API. You can check out the code used in this tutorial in this Github repo.
Customized Technical Learning Solutions to Help Attract and Retain Talented Developers
Let DI help you design solutions to onboard, upskill or reskill your software development organization. Fully customized. 100% guaranteed.
DevelopIntelligence leads technical and software development learning programs for Fortune 500 companies. We provide learning solutions for hundreds of thousands of engineers for over 250 global brands.
“I appreciated the instructor’s technique of writing live code examples rather than using fixed slide decks to present the material.”
VMwareThank you for everyone who joined us this past year to hear about our proven methods of attracting and retaining tech talent.
© 2013 - 2020 DevelopIntelligence LLC - Privacy Policy
Let's review your current tech training programs and we'll help you baseline your success against some of our big industry partners. In this 30-minute meeting, we'll share our data/insights on what's working and what's not.
Training Journal sat down with our CEO for his thoughts on what’s working, and what’s not working.