Skip to content

ewendel/react-workshop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React workshop

Slides from the presentation are available here

Instructions

Ensure that you have Node.js installed, otherwise install from https://nodejs.org/.

Clone this repo:

git clone https://github.com/ewendel/react-workshop.git
cd react-workshop

Install the project's dependencies:

npm install

Start the webserver:

node app.js

Tasks

Below you'll find all the tasks we will be working with in this workshop. For the first part of this workshop we have already created all the files you'll need to solve these tasks, so you don't have to create any new files yourself. You can find all the files needed in the the tasks folder, where you should also solve the tasks.

In these files, the source code for React.js and a JSX-transpiler are already included so that we do not need to continously build our frontend code while developing. Some of the exercises include pre-written CSS, so you shouldn't have to write any CSS (unless you want to spice things up, of course)

To get started, go to: http://localhost:3000

Remember to peek at React's documentation while working on the tasks.

Part I: Becoming aquainted with React

Task 1: Creating your first component

(For this task, edit the files in directory /tasks/1/. The changes should be visible in http://localhost:3000/1)

Create a simple React component that prints "Hello World".

To solve this task we need to create a React component, implement a render method in the component, and then render the React component into the DOM.

Tips

Helpful links:

Task 2: Passing data & using JSX

Expand the component from ex. 1 to take in a property called name from its parent and write out "Hello, {name}".
If the component is not passed a prop it should use "World" as a default value.

Next, create a component called Helloesthat accept a property names (array) and utilizes the previous component to write out "Hello, {name}" for each of the names in the names-array.

Tips

props are used to pass data from parent to child components - reached via this.props and are immutable.

render() should only return a single node

Remember that you can use ordinary JavaScript in JSX by using { } to escape.

Helpful methods: Array.prototype.map

Helpful reading: Lists and keys in React

Task 3: Stateful components: Timer

Create a component called Timer that prints out the time passed since the component was initially rendered. Example:

I was started 7.8 seconds ago

The component should update itself 10 times per second, and the component should perform any necessary cleanup when unmounted, e.g timer methods.

Tips

We use state to store our data that changes during the lifetime of a component. It can be accessed through this.state

Helpful methods: setInterval, clearInterval

Lifecycle hooks: componentDidMount, componentWillUnmount Read about state and lifecycle hooks in the docs

To unmount the component, use the ReactDOM.unmountComponentAtNode helper, e.g.

setTimeout(function() {
    ReactDOM.unmountComponentAtNode(...);
}, 3000);

Task 4: More state: Real-time search

Create a component Search that is passed an array called items (a prop). The elements contained in the array will have the following format: { name: 'Some string', url: 'www.somesite.com' }

The component should include a text field, and the elements in the array should be filtered by which ones contain the current string in the input field. The HTML-structure should look like this:

<div>
    <input />
    <ul>
        <li><a ...></a></li>
        <li><a ...></a></li>
        <li><a ...></a></li>
    </ul>
</div>

Also - ensure the input field has focus after the component has been rendered.

Tips

Helpful methods: String.prototype.match, Array.prototype.filter

Useful attributes in JSX: onChange, refs, className (because class is a reserved keyword in JavaScript)

--

Part II: Twitter Dashboard

In this task you will create a super-cool Twitter Dashboard.

Setup

If you do this workshop outside of a conference, you have to get access to the Twitter API before you start working on the tasks. Follow the guide in twitter-setup.md to get access and setup the correct files.

NB! If you're at a conference with us you DON'T have to set up Twitter API access!

Local setup

Go to the case/task folder, then start by installing dependencies and starting the development tool:

cd case/task

npm install

npm start

Here we've run the bootstrapping tool create-react-app, which sets up all the build tools we'll need to create even advanced production apps.

npm start starts a development server, which automatically recompiles your code on every change. Pretty neat, huh? It'll even open your browser window to the correct address!

Then, start the server in another terminal window (remember to go the the case/task folder first) with npm run server.

You should see the text "Dashboard".

Step-by-step guide

Task 1: Rendering a single tweet

Create a component, Tweet, in src/components that accepts a tweet object and renders this. For now, use this component from the Dashboard component.

As we still haven't fetched tweets from Twitter, you can use the example tweet object found in case/task/example-tweet.json. As a hint, in Node you can actually require a json file directly:

var jsObject = require('./some-file.json');

The Tweet component should have the following HTML structure (which gives you some free CSS):

<div class="tweet">
    <div class="tweet-header">
        <img class="tweet-image" src="some/url/image.jpg" />
        <div class="tweet-image-offset tweet-name">Knut Olav</div>
        <div class="tweet-image-offset tweet-screen-name">@VerdensKongen</div>
    </div>

    <div class="tweet-text">Hello, fellow developers!</div>
    <div class="tweet-stats">
        <span class="tweet-user-followers">
            <strong>12,058</strong>
            <span class="tweet-stats-desc">followers</span>
        </span>
    </div>
    <span class="tweet-flag flag-icon flag-icon-no"></span>
    <span class="tweet-country tweet-stats-desc">Norge</span>
    <div class="tweet-city tweet-stats-desc">Langesund, Telemark</div>
</div>

(Remember that class and className are not the same)

Take note of the element with the class flag-icon-no, where the two last letters incide the country code of the tweet's origin. (i.e. no for Norway).

Task 2: Fetching real tweets

Afterwards, set up a WebSocket connection to the server in order to receive tweets from the API. This should be done in the Dashboard component when it is mounted. Pass the most recently received tweet to the Tweet component. (For easier debugging we don't push that many tweets yet, so it might take a few seconds between each new tweet.)

Here's a list of lifecycle methods available in React:

This is the code needed to set up a WebSocket connection and receive tweets:

NOTE! If you haven't been through the Twitter API setup, remember to ask us for the correct IP address to use instead of localhost!

const ws = new WebSocket('ws://localhost:9999');
ws.onmessage = (ms) => {
    var newTweet = JSON.parse(ms.data);
    // TODO: Do something with this tweet data!
};

Task 3: A list of tweets

Expand the Dashboard component to render a list of all received tweets in a <ul>. This list should have the class tweetlist.

Move all the code related to showing this list into a new component TweetList, that receives a list of tweets to render. Only render the last three received tweets.

Note: you should still use the Tweet component created earlier to render each individual tweet.

Task 4: Tweets on a map

Time to plot where on earth all these tweets are coming from!

We will use the component called react-google-maps (ensure that you choose the right package, as there are others with similar names).

Now run npm install <package name> to install this package.

Create a TweetMap component that you use from the Dashboard component. This new component should render a top-level div with the CSS class tweet-map. With the help of the react-google-maps documentation, render a simple map into this div.

These settings are a good starting point for the map:

  • defaultZoom: 3
  • defaultCenter: { lat: 30.675226, lng: -35.051272 }

Here's a working example you can play with: https://codesandbox.io/s/2xyw6n4o9y

Each tweet has a geolocation. Use this to the place a marker on the map for each tweet.

(If you have set up the Twitter API access yourself, you can control the rate at which you receive tweets on the frontend. In task/twitter-ws.js, change the value of the currentSpeed variable to some other value, then restart the backend, i.e. re-run npm start.)

It can be wise to only use, let's say, the last hundred received tweets in order to avoid your computer from crashing due to the vast amounts of data.

Task 5: Influential tweets

Now that we are receiving more tweets, it is becoming harder to read the tweets in our TweetList. Change this component to show the three tweets that have the most followers amongst the tweets that are shown on the map.

Task 6: Current tweet

We want to to be able to click on one of our map markers in order to highlight and show that tweet. Make a new component CurrentTweet to be used for displaying the selected tweet. It should use the Tweet component to render the tweet, and for some free styling, you can use the class current-tweet.

The selected tweet should have its own marker color. The Marker component accepts a prop called icon that takes an image url. Here are some suitable images that can be used:

http://maps.google.com/mapfiles/ms/icons/red-dot.png
http://maps.google.com/mapfiles/ms/icons/yellow-dot.png
http://maps.google.com/mapfiles/ms/icons/blue-dot.png
http://maps.google.com/mapfiles/ms/icons/green-dot.png

Hint: Remember that you can pass functions into a component as a prop, e.g. as with onChange in forms.

Hint 2: It's possible to pass along all props to child components: docs.

Task 7: shouldComponentUpdate

Considering the amount of incoming tweets, it could be wise to help React understand whether it needs to check if a component has changes that should be rendered to the DOM. (That is, when a call to render() would produce the same output as the previous call).

By using console.log in the render-method of our CurrentTweet component we can see how often it is called. Check this again after having implemented the lifecycle method shouldComponentUpdate. See the docs for how this method works.

Task 8: App Header

Our app needs a header. In addition to showing the app name (which is yours to decide), it should display the number of seconds that has passed since it started running (sounds familiar?) and the number of tweets it has processed so far.

The HTML could look something like this:

<div class="app-header">
    <h1>Crazy-name, yo</h1>
    <div>
        <span class="tweet-stats-desc">seconds running</span>
        <strong>12</strong>
    </div>
    (similar for no. of tweets)
</div>

(Remember to reuse the Timer component you created in part 1!)

Task 9: Country statistics

We would like to display which countries that create the most tweets. Create a component CountryList that does this. It should take into account all tweets ever received, not just the last hundred.

The HTML could look like this:

<ul class="countrylist">
    <li>
       <span class="tweet-flag flag-icon flag-icon-no"></span>
       <span class="country-tweet-count">25</span>
    </li>
</ul>

Hint: You don't need to keep a record of all the tweets, only the number of tweets per country.

Task 10: Creating a "shared" component

We are now displaying small flag icons in two different places in our app. It is not beneficial to have this code duplication, so refactor this into a Flag component.

--

Finished!

Now you should have quite a good grasp of how React works. If you want to learn more about using React in large apps, you should take a look at Redux, the most recognized implementation of the Flux pattern.

The author, Dan Abramov, has created a brilliant online course on Redux available on egghead.io.

Articles

Videos

About

React.js Workshop

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published