Building TrumpOS, a React Webapp

If you followed my previous post, you should have everything you need to start programming with react.

I want to build what I imagine Trump's smartphone homescreen looks like, and each of his "apps" would be made of react components. Today, we'll build our first custom component. A Trump tweet generator. With a simple touch of a button, it will spew out one of his angry robotic tweets.

create a new folder at src/components and another one in there at src/components/twitter

Let's create a simple view, which will render child components later on, such as the button for the tweet generator. Let's keep it simple for now:

src/components/twitter/TwitterView.js:

import React from 'react';

var TwitterView = React.createClass({
  render: function () {
    return <div></div>;
  }
});

export default TwitterView;

In the first line, we're importing react, which will allow us to write jsx code, beautifully mixing html elements with javascript.

Next we create a variable, called TwitterView, and give it the value of a call to react's createClass function.

React classes need a render function as one of their parameters. For now, we'll just return an empty div.

In the last line, we export our variable. This is what will be used if we import this component somewhere else.

next, let's build our TweetGenerator in the same folder.

src/components/twitter/TweetGenerator.js

import React from 'react';

now let's analyse Trump's vocabulary, and come up with greetings, subjects, and exclamations:

var greetings = ['hello ','Good morning, ','The sun is shining again today thanks to me, ', 'What\'s the deal with the fact that, '];

var subjects = ['liberal media is lying. ','obamacare is a disaster. ', 'these trade deals are a disaster. ','mexico is taking our jobs. '];

var exclamations = ['SAD!','FAKE NEWS','DISHONEST','MAKE AMERICA GREAT AGAIN'];

Next let's add a simple random int function, we'll use it to randomly pick parts of the tweet.

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

then, we'll start working on our TweetGenerator class

First we need to pass a function called getInitialState. This is a react specific function, which just returns the initial state of our component's variables, in our case an empty sentence.

var TweetGenerator = React.createClass({
  getInitialState: function () {
    return {sentence: ''};
  },

Next we'll add a randomSentence funcion, which will build tweets out of our arrays using our randomInt function. It will then set the state of our sentence variable.

  randomSentence: function()  {
    var newSentence = greetings[getRandomInt(0,4)] + subjects[getRandomInt(0,4)] + exclamations[getRandomInt(0,4)];
    this.setState({ sentence: newSentence});
  },

We'll also need to render two elements. A button that calls our randomSentence function onClick, and a p tag to contain our sentence. {this.state.sentence} is in curly braces, because that's how we inject javascript into our jsx html elements.
this.state refers to the current state of our component's variables. Remember, the state of the sentence variable will change each time we click the button, and the component will rerender each time a state changes.

  render: function () {
    return (
      <div>
        <button onClick={this.randomSentence}>TWEET</button>
        <p>{this.state.sentence}</p>
      </div>
    );
  }
});

Finally we should export our class:

export default TweetGenerator;

Next we want to render our class in our twitter view, remember, components can render other components!

We'll need to import our TweetGenerator class and store it in a variable. This variable will only contain what we chose to export in the last line of the component.

Then we can add <TweetGenerator /> to our div like so:

src/components/twitter/TwitterView.js:

import React from 'react';
import TweetGenerator from './TweetGenerator.js';


var TwitterView = React.createClass({
  render: function () {
    return (
        <div>
          <TweetGenerator />
        </div>
    );
  }
});

export default TwitterView;

Now we need to render this view in our webapp:

src/app.js

import React, { Component } from 'react';
import './assets/css/App.css';
import TwitterView from './components/twitter/TwitterView.js';

class App extends Component {
  render() {
    return (
      <div className="App">
        <TwitterView />
      </div>
    );
  }
}

export default App;

If you haven't changed anything in index.js, our tweetgenerator should be rendered in our app. But let's take a look at what index.js actually does:

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './assets/css/index.css';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

As we can see, it imports ReactDOM. This is the class that allows us to render our virtual DOM in the real DOM, by calling ReactDOMs render function, with two parameters. 1: the component we want to render: <App />, and where it will be rendered in our html: An element with id="root".

Take a look at public/index.html and you'll see this: <div id="root"></div>. That's where our app will be rendered.

Congrats, you just built a react app! Now there are endless opportunities to build upon this little foundation of ours.

Use the map() function to render a component for each tweet

If you continue reading you'll see how I used props and the handy map() function to get a more twitter.com like feel.

I made this tweet component, take a look at the p tag, it contains {this.props.tweet}.

import React from 'react';
import trumpFace from '../../assets/trump.jpg';
import  '../../assets/css/Tweet.css';

var Tweet = React.createClass({
  render: function () {
    if(this.props.tweet) {
      return (
          <div className="tweet">
            <img src={trumpFace} className="trumpProfile" alt="logo" />
            <span className="realName">Donald J. Trump</span>
            <span className="userName">@theRealDonaldTrump</span>
            <p>{this.props.tweet}</p>
          </div>
      );
    }
    else return null;
  }
});

export default Tweet;


This means that when we render this component from somwhere else, we can pass a prop to it, like so:

<Tweet key={sentence} tweet={sentence} />

I updated my TweetGenerator class accordingly.

The randomSentences function now sets the state like this:

this.setState({ sentences: [newSentence].concat(this.state.sentences)});

and the render return statement looks like this:

<div>
  <button onClick={this.randomSentence}>TWEET</button>
  {this.state.sentences.reverse().map(sentence => (
    <Tweet key={sentence} tweet={sentence} />
  ))}
</div>

Now it adds each tweet to an array, and renders the whole list of tweets.

Here's what we covered:

  • How components are structured
  • The render() function in a component
  • How components can render other components
  • states, getInitialState, setState
  • The onClick event listener
  • Using {curly braces} to inject JavaScript into Jsx Html elements
  • A quick look at the ReactDOM
  • And we built a simple React Webapp!