Image for post
Image for post

Creating Premier League Player Cards with React JS

The content below is based on Kirupa Chinnathambi’s “Learning React” Youtube series. I adapted this content to serve as documentation for myself and to help others who enjoy learning through written tutorials.

This tutorial starts out mimicking the content in Kirupa’s Learning React, but then deviates as I add my own spin on the project. If you’re into Soccer/Football/Futbol this will likely be a little more interesting for you as I focus the project on building “English Premier League Player Cards” that look something like this:

Image for post
Image for post

I think it’s a good practice to focus your work on a theme that you enjoy. For me, it’s soccer. What is the theme for you? What theme gets you excited? Feel free to update the content with whatever makes you a little more interested.

And yes, thank you in advance to all of the wonderful folks that will remind me that Eden Hazard no longer plays in the EPL.

Anyways, I hope you have fun learning React. I certainly am!

Let’s dive in!

Image for post
Image for post

Step 1: Introduction to React

Before we get started, it’s worth taking a look at Kirupa’s Introduction video here. This will answer many questions you didn’t even know you had about React :)

What is React? React is a JavaScript library — created at Facebook — for building single-page user interface applications.

In the MVC perspective — Model, View, Controller, that is — React is responsible for handling the View. Therefore, React must be used in conjunction with other frameworks that will contribute the Model and Controller responsibilities of an application.

In this example, we’ll hardcode data directly into our HTML document that will contain our React Scripts. It’s an easy way to jump right in and get a taste of what React is all about.

Ok, let’s get started!

Step 2: Hello, world!

To get started set up an HTML document:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React, React, React</title>
</head>
<body>
</body>
</html>

Make sure to set the meta charset to utf-8 as I’ve done above.

Then, add the necessary libraries for React and Babel into the head of your HTML document.

We must use Babel because we’re working with JSX and we need to translate into regular HTML / CSS / JavaScript (link to video).

The three scripts are (as of the writing of this tutorial June 15, 2018):

<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script><script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

Next, we will add a function for printing content. The function is called ‘render’. Let’s add it to our HTML document inside <script> tags and inside the <body>:

<body>
<script>
ReactDOM.render();
</script>
</body>

Render take two arguments (link to video):

  1. The thing we want to print; the JSX
  2. The element we will print our content to

Inside the render function, we’ll write:

ReactDOM.render(
<div>
<h1>Hello, world!</h1>
</div>
);

We’ve written the first argument: adding the JSX — which really just resembles HTML right now, but we also need to add our second argument: the element we will print our content to. We’ll call it destination

ReactDOM.render(
<div>
<h1>Hello, world!</h1>
</div>,
destination
);

But what is destination ?

We need to create a variable called destination and assign is a value in the DOM. In other words, we need to assign the destination location to the variable destination .

var destination = document.querySelector("#theDestination")

If you’re familiar with Javascript already you’ll be able to translate this. We’re selecting a destination that is signaled by the class “theDestination”. But we haven’t actually created this destination yet, so let’s jump into our HTML and do that:

<div id="theDestination"></div>

Cool.

Your document should look something like:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React! React! React!</title>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="theDestination"></div>
<script type="text/babel">
var destination = document.querySelector("#theDestination")
ReactDOM.render(
<div>
<h1>Hello, world!</h1>
</div>,
destination
);
</script>
</body>
</html>

And if you pull up the file in our browser, it will look something like this:

Image for post
Image for post

Now let’s add some styling.

For now, we are going to add the style tags directly into the document <head>:

<style>
#theDestination {
padding: 50px;
background-color: #EEE;
}
#theDestination h1 {
font-size: 144px;
font-family: sans-serif;
color: #0080A8;
}
</style>

Refresh your HTML file in your browser, and you’ll see:

Image for post
Image for post

Lovely.

Step 3: Components & Props (and handling children)

Before we dive into section 3 here, just another disclaimer that this content is based on Kirupa Chinnathambi’s youtube series Learning React. Kirupa’s video on Components in React is available here.

Insert useful quote:

“Components define the visuals and interactions that make up what people see in your app.”

Components break up our visuals into separate entities.

To nail this concept home, let’s jump back into our editor and start writing some code.

Inside the render function, let’s add a few more <h1> elements.

But first, a quick note on making things fun for yourself. It’s pretty easy to do, and adding a little fun-spice helps me learn a little faster and think about things more creatively in the context of something I might actually want to build. Try it out! The easiest way to add some fun-spice is to use data that you are interested in.

Me? I love soccer, and love to watch English Premier League, so I’ll use some of last year’s top performers in the league for my example. Feel free, of course, to use whatever you like for your own work. Add whatever “fun-spice” you like:

ReactDOM.render(
<div>
<h1>Mohamed Salah</h1>
<h1>Eden Hazard</h1>
<h1>Raheem Sterling</h1>
<h1>Sadio Mané</h1>
<h1>Andrew Robertson</h1>
</div>,
destination
);

Reduce font-size a bit to accommodate 5 elements…

#theDestination h1 {
font-size: 72px;
font-family: sans-serif;
color: #0080A8;
}

Refresh your browser, annnnd baboom:

Image for post
Image for post

Nothing all that special yet. Moving on.

Now let’s pretend we want to update all of these <h1> tags to <h3> tags. Rather, let’s not pretend, let’s do it. And make sure you’re typing this, folks. Good to get that muscle memory in place.

ReactDOM.render(
<div>
<h3>Mohamed Salah</h3>
<h3>Eden Hazard</h3>
<h3>Raheem Sterling</h3>
<h3>Sadio Mané</h3>
<h3>Andrew Robertson</h3>
</div>,
destination
);

and now let’s italicize everything…

ReactDOM.render(
<div>
<h3><i>Mohamed Salah</i></h3>
<h3><i>Eden Hazard</i></h3>
<h3><i>Raheem Sterling</i></h3>
<h3><i>Sadio Mané</i></h3>
<h3><i>Andrew Robertson</i></h3>
</div>,
destination
);

Geez that was tedious.

You can feel the repetitiveness of this, right? That's where functions come in. Functions can help reduce the repeat. (link to video at this moment)

Alright, let’s rewind a bit before we fast forward to help nail this concept of “functions reducing the repetition” on to our growing understanding of components.

Let’s reverse back to our <h1>Hello, world!<h1> code:

<script type="text/babel">
var destination = document.querySelector("#theDestination")
ReactDOM.render(
<div>
<h1>Hello, world!</h1>
</div>,
destination
);
</script>

We’ll write a component called HelloWorld:

class HelloWorld extends React.Component {
render() {
return <h1>Hello, world!</h1>
}
}

Now, inside our ReactDOM.render() method, we’ll write <HelloWorld/> :

ReactDOM.render(
<div>
<HelloWorld/>
</div>,
destination
);

Save, refresh the page in your browser, and….

Image for post
Image for post

Cool. The same, but different.

Ok, that was cool, but let’s dive a little deeper. Next, well learn how to use properties to pass arguments into our components.

Inside our HelloWorld class, write:

class HelloWorld extends React.Component {
render() {
return <h1>{this.props.greetTarget}</h1>
}
}

Let’s break this down.

  • The {}, what do they do? They specify a region that’s going to be an expression, or the result of an expression evaluation, rather than just prining the raw text on the screen. (link to video at this moment)
  • The “this.props”, what does that do? This is React’s internal name for the argument. Sort of like a “hey, React! There’s an argument coming”
  • Then the “greetTarget” is the name you’ll give the argument. Remember when we told React an argument was coming? This is the name of the argument.

(if you have a better understanding than I of what these actually mean, please leave a comment and help keep the education train rolling. choo-choo)

Alright, moving on with the lesson. Let’s add some fun-spice back into our document. Copy/past down <HelloWorld/> like so:

<script type="text/babel">
var destination = document.querySelector("#theDestination")
class HelloWorld extends React.Component {
render() {
return <h1>{this.props.greetTarget}</h1>
}
}
ReactDOM.render(
<div>
<HelloWorld/>
<HelloWorld/>
<HelloWorld/>
<HelloWorld/>
<HelloWorld/>
</div>,
destination
);
</script>

And then let’s add our argument to each line:

<HelloWorld greetTarget="Mohamed Salah"/>
<HelloWorld greetTarget="Eden Hazard"/>
<HelloWorld greetTarget="Raheem Sterling"/>
<HelloWorld greetTarget="Sadio Mané"/>
<HelloWorld greetTarget="Andrew Robertson"/>

Save, refresh the page. Annnnnd:

Image for post
Image for post

Great. Working the way it’s supposed to. Remember when we italicized and changed all the <h1>s to <h3>s above? In this new scenario, we just need to update the format and style in one single place instead of in 5 places.

Now let’s actually say “Hello” to each player. They each deserve it. Outstanding 18/19 seasons all around.

To do this, we’ll just update our HelloWorld class, adding Hello, before the expression evaluation and ! after:

class HelloWorld extends React.Component {
render() {
return <h1>Hello, {this.props.greetTarget}!</h1>
}
}

Save, refresh. Neat.

Image for post
Image for post

Cool. Now, let’s move on the “Dealing with children” (link to video at this moment):

You know what child elements are, right?

<div>
<h1>
<p></p>
</h1>
</div>

<h1> is a child of <div>

<p> is a child of <h1> and a child of <div>

Great. Now that that’s been covered, let’s create another component that deals with child elements.

First a new component:

class Buttonify extends React.Component {
render () {
return (
<div>
<button type={this.props.behavior}></button>
</div>
);
}
}

Then, render in the DOM:

ReactDOM.render(
<div>
<Buttonify behavior="submit"></Buttonify>
</div>,
destination
);

Save, refresh, and walah! A button:

Image for post
Image for post

Pretty boring as far as buttons go, though. It doesn’t do anything! Buttons are better when they do stuff, don’t you agree?

First, let’s write some copy inside the component rendered in the DOM:

ReactDOM.render(
<div>
<Buttonify behavior="submit">DO SOMETHING GREAT!</Buttonify>
</div>,
destination
);

Save, refresh your HTML in the browser, and what do you see? Not a whole lot!

To fix that nothingness, let’s add this.props.children to our component:

class Buttonify extends React.Component {
render () {
return (
<div>
<button type={this.props.behavior}>{this.props.children}</button>
</div>
);
}
}

Now save, refresh, and it’s a whole new ballgame:

Image for post
Image for post

Our component now extends to the children. Great!

Now let’s wrap this section up with some JSX “Stuff to keep in mind” (link to video at this moment):

  1. Your components must always be capitalized
  2. Inside render , you output the JSX you want to return
  3. To evaluate an expression, wrap it inside { }
  4. You can call a component directly by wrapping its name in < and > characters

Step 4: Styling in React

If you’d like to watch along, Kirupa’s link to video here.

In React, there are two ways to style content:

  1. Use CSS and style tags (the traditional approach)
  2. Create an object that contains style properties and apply everything in code

Alright, let’s start with a clean slate:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Styling in React</title>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
</body>
</html>

We’ll add a div to the body, and assign the div an id called “container”:

<div id="container"></div>

Then we’ll add a script tag and use ReactDOM.render to insert a div tag with some content:

<body>
<div id="container"></div>
<script type="text/javascript">
var destination = document.querySelector("#container");
ReactDOM.render(
<div>
<Player>Mohamed Salah</Player>
<Player>Eden Hazard</Player>
<Player>Raheem Sterling</Player>
<Player>Sadio Mané</Player>
<Player>Andrew Robertson</Player>
</div>,
destination
);
</script>
</body>

What’s missing here?

The definition of our component Player !

Let’s add:

class Player extends React.Component {
render () {
return(
<div>
{this.props.children}
</div>
);
}
}

Save, refresh your HTML file in your browser, and what do you see?!?

Image for post
Image for post

A big fat nothing. That’s because we forgot to specify the script type.

Change <script type="text/javascript"> to <script type="text/babel"> .

Save, refresh, and we are rewarded with:

Image for post
Image for post

Beautiful. Out of curiosity 100% not related to this tutorial, who is your favorite soccer player?

Now we have our super-cool content elements, and next we’re going to style. Lesssss go!

In the <head>, inside a <style> tag:

<style type="text/css">
div div div {
padding: 10px;
margin: 10px;
background-color: #FFDE00;
color #333;
display: inline-block;
font-family: monospace;
font-size: 32px;
text-align: center;
}
</style>

Looks familiar, right?

If you’re wondering why we had to call div div div to target our component elements, look back at your code and trace how our elements are nested. You’ll see that these Player elements are nested 3 div’s deep.

Page should look like:

Image for post
Image for post

Next, we’ll refactor the way we’re targetting the player div:

Instead of div div div , we’ll create a class called .player

<style type="text/css">
.player {
padding: 10px;
margin: 10px;
background-color: #FFDE00;
color #333;
display: inline-block;
font-family: monospace;
font-size: 32px;
text-align: center;
}
</style>

And then let’s make sure our element is aware of this new class:

class Player extends React.Component {
render () {
return(
<div className="player">
{this.props.children}
</div>
);
}
}

Notice we use className="player” instead of class="player" . Similar to HTML, but slightly different.

Alright, that was the “traditional” way of styling, now let’s look at React’s way of styling:

Remove the style class name from the Player component:

class Player extends React.Component {
render () {
return(
<div>
{this.props.children}
</div>
);
}
}

Now we’ll write a style object in javascript, and apply to our Player class. Let’s do it:

First, we’ll create a variable called playerStyle, and assign it our style values:

var playerStyle = {
padding: 10,
margin: 10,
backgroundColor: "#FFDE00",
color: "#333",
display: "inline-block",
fontFamily: "monospace",
fontSize: "32px",
textAlign: "center"
};

You’ll notice some small differences between this and our CSS.

Next, we’ll assign the style to our <div> containing our Player elements:

return(
<div style={playerStyle}>
{this.props.children}
</div>
);

All together, the Player class looks like:

class Player extends React.Component {
render () {
var playerStyle = {
padding: 10,
margin: 10,
backgroundColor: "#FFDE00",
color: "#333",
display: "inline-block",
fontFamily: "monospace",
fontSize: "32px",
textAlign: "center"
};
return(
<div style={playerStyle}>
{this.props.children}
</div>
);
}
}

Save, refresh, andddddddd

Image for post
Image for post

Walah. Same but different.

Image for post
Image for post

Right click, “Inspect”, and see that all the CSS was applied individually, inline to each element.

Next we’ll get a little creative and assign each Player element an individual background-color:

Our variable will be called bgColor and we’ll add it to each Player element within our ReactDOM.render() call:

ReactDOM.render(
<div>
<Player bgColor="#DB1642">Mohamed Salah</Player>
<Player bgColor="#DFE3E8">Eden Hazard</Player>
<Player bgColor="#9DCEF0">Raheem Sterling</Player>
<Player bgColor="#DB1642">Sadio Mané</Player>
<Player bgColor="#DB1642">Andrew Robertson</Player>
</div>,
destination
);

Now we have to add knowledge of this component to our Player class:

backgroundColor: this.props.bgColor,

instead of

backgroundColor: "#FFDE00",

The Player class should look like:

class Player extends React.Component {
render () {
var playerStyle = {
padding: 10,
margin: 10,
backgroundColor: this.props.bgColor,
color: "#333",
display: "inline-block",
fontFamily: "monospace",
fontSize: "32px",
textAlign: "center"
};
return(
<div style={playerStyle}>
{this.props.children}
</div>
);
}
}

Refresh your page, addddddd:

Image for post
Image for post

Neato. Eden Hazard off to Madrid. Will Liverpool manage to hold on to their playmakers from 2018/19? I think so, but what do I know?

Notice that this.props.bgColor is not wrapped in curly braces like property calls are wrapped elsewhere in our code. That’s because the style region of our code is not JSX, it’s javascript. (Check out the video here to get this quick lesson.)

Allllllright, that’s it on styling for now. Moving on.

Step 5: Creating Complex Components

If you’d like to watch along, Kirupa’s link to video here.

For this lesson, we’re going to do something very similar but slightly different. Let’s create some Soccer Player Cards! Our end result will look like:

Image for post
Image for post

Before we get started here, I highly recommend checking out the 2–3 minute segment of this video where Kirupa talks about thinking through component hierarchy and how to think about breaking down your UI into individual components. Watch here.

Let’s build, starting with a fresh page:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mohamed Salah Player Card</title>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<style type="text/css">
#container {
padding: 50px;
background-color: #FFF;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var destination=document.querySelector("#container");
ReactDOM.render(
<div>
</div>,
destination
);
</script>
</body>
</html>

Cool. First thing we’ll do is start defining our 3 components:

  1. PlayerImage
  2. Label
  3. Card
class PlayerImage extends React.Component {
render () {
return(
<br/>
);
}
}
class Label extends React.Component {
render () {
return(
<br/>
);
}
}
class Card extends React.Component {
render () {
return(
<br/>
);
}
}

Three components that are doing a whole lot of nothing. Let’s change that, starting with styling the Card component:

var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)"
};

Check out the video here to understand why we need to add WebkitFilter to our styling. filter is something that doesn’t have universal support, so we need to prefix filter and add WebkitFilter to make sure our code works across browsers.

Now return a <div> with style={cardStyle} :

class Card extends React.Component {
render () {
var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)"
};
return(
<div style={cardStyle}>

</div>
);
}
}

Then, in ReactDOM.render() print out the Card element:

ReactDOM.render(
<div>
<Card/>
</div>,
destination
);

Save, refresh, andddddd:

Image for post
Image for post

Cool. We’re well on our way to a super-neat Mo’ Salah player card and a few others…

Now for the PlayerImage component:

First, we’ll create the stylings:

var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + "https://imgur.com/NVLuLLY.png" + ")",
backgroundSize: "cover"
}

Then we'll assign the style variable playerImageStyle to the <div> returned by our PlayerImage class:

return(
<div style={playerImageStyle}>
</div>
);

All together now:

class PlayerImage extends React.Component {
render () {
var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + "https://imgur.com/NVLuLLY.png" + ")",
backgroundSize: "cover"
}
return(
<div style={playerImageStyle}>
</div>
);
}
}

Then all we need to do is….

Return the <PlayerImage/> class inside our Card component:

return(
<div style={cardStyle}>
<PlayerImage/>
</div>
);

All together now:

<body>
<div id="container"></div>
<script type="text/babel">
var destination=document.querySelector("#container");
class PlayerImage extends React.Component {
render () {
var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + "https://imgur.com/NVLuLLY.png" + ")",
backgroundSize: "cover"
}
return(
<div style={playerImageStyle}>
</div>
);
}
}
class Label extends React.Component {
render () {
return(
<br/>
);
}
}
class Card extends React.Component {
render () {
var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)"
};
return(
<div style={cardStyle}>
<PlayerImage/>
</div>
);
}
}
ReactDOM.render(
<div>
<Card/>
</div>,
destination
);
</script>
</body>

Save, refresh your page, annnnnddd:

The Egyptian King himself:

Image for post
Image for post

Namaste, my friend.

Now let’s add some of our other top-performers. We’ll need to refactor a bit.

We need to set the image URL at the card level so that we can have cards with different images:

var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + this.props.imgUrl + ")",
backgroundSize: "cover"
}

and then:

<div style={cardStyle}>
<PlayerImage imgUrl={this.props.imgUrl}/>
</div>

and then update the card style:

var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)",
display: "inline-block",
margin: "15px"
};

and then:

ReactDOM.render(
<div>
<Card imgUrl="https://imgur.com/SUbruAW.png"/>
<Card imgUrl="https://imgur.com/nBNG4wI.png"/>
<Card imgUrl="https://imgur.com/pnVajXW.png"/>
<Card imgUrl="https://imgur.com/0b6NIeE.png"/>
<Card imgUrl="https://imgur.com/FDOwiqr.png"/>
</div>,
destination
);

Cool.

Save, refresh, aaaaaand baboom!

Image for post
Image for post

Neat.

Next, let’s build out the Label component and give each player a name:

First, some style:

var labelStyle = {
fontFamily: "sans-serif",
fontWeight: "bold",
padding: "13px",
margin: 0
};

Then, like before with the URL, we’ll set the player name at the Card level:

ReactDOM.render(
<div>
<Card imgUrl="https://imgur.com/SUbruAW.png" playerName="M. Salah"/>
<Card imgUrl="https://imgur.com/nBNG4wI.png" playerName="E. Hazard"/>
<Card imgUrl="https://imgur.com/pnVajXW.png" playerName="R. Sterling"/>
<Card imgUrl="https://imgur.com/0b6NIeE.png" playerName="S. Mané"/>
<Card imgUrl="https://imgur.com/FDOwiqr.png" playerName="A. Robertson"/>
</div>,
destination
);

Then, pass the playerName into the Card component:

class Card extends React.Component {
render () {
var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)",
display: "inline-block",
margin: "15px"
};
return(
<div style={cardStyle}>
<PlayerImage imgUrl={this.props.imgUrl}/>
<Label playerName={this.props.playerName}/>
</div>
);
}
}

And finally, pass the playerName into the Label component:

class Label extends React.Component {
render () {
var labelStyle = {
fontFamily: "sans-serif",
fontWeight: "bold",
padding: "13px",
margin: 0
};
return(
<p style={labelStyle}>
{this.props.playerName}
</p>
);
}
}

Save, refresh, neato:

Image for post
Image for post

All the code:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mohamed Salah Player Card</title>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<style type="text/css">
#container {
padding: 50px;
background-color: #FFF;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var destination=document.querySelector("#container");
class PlayerImage extends React.Component {
render () {
var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + this.props.imgUrl + ")",
backgroundSize: "cover"
}
return(
<div style={playerImageStyle}>
</div>
);
}
}
class Label extends React.Component {
render () {
var labelStyle = {
fontFamily: "sans-serif",
fontWeight: "bold",
padding: "13px",
margin: 0
};
return(
<p style={labelStyle}>
{this.props.playerName}
</p>
);
}
}
class Card extends React.Component {
render () {
var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)",
display: "inline-block",
margin: "15px"
};
return(
<div style={cardStyle}>
<PlayerImage imgUrl={this.props.imgUrl}/>
<Label playerName={this.props.playerName}/>
</div>
);
}
}
ReactDOM.render(
<div>
<Card imgUrl="https://imgur.com/SUbruAW.png" playerName="M. Salah"/>
<Card imgUrl="https://imgur.com/nBNG4wI.png" playerName="E. Hazard"/>
<Card imgUrl="https://imgur.com/pnVajXW.png" playerName="R. Sterling"/>
<Card imgUrl="https://imgur.com/0b6NIeE.png" playerName="S. Mané"/>
<Card imgUrl="https://imgur.com/FDOwiqr.png" playerName="A. Robertson"/>
</div>,
destination
);
</script>
</body>
</html>

Step 6: Going from Data to UI

Kirupa’s video here.

The starting point for this section will be the following code:

<DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Mohamed Salah Player Card</title>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<style type="text/css">
#container {
padding: 50px;
background-color: #FFF;
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var destination=document.querySelector("#container");
class PlayerImage extends React.Component {
render () {
var playerImageStyle = {
height: "150px",
backgroundImage: "url(" + this.props.imgUrl + ")",
backgroundSize: "cover"
}
return(
<div style={playerImageStyle}>
</div>
);
}
}
class Label extends React.Component {
render () {
var labelStyle = {
fontFamily: "sans-serif",
fontWeight: "bold",
padding: "13px",
margin: 0
};
return(
<p style={labelStyle}>
{this.props.playerName}
</p>
);
}
}
class Card extends React.Component {
render () {
var cardStyle = {
height: "200px",
width: "150px",
padding: 0,
backgroundColor: "#FFF",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #666)",
display: "inline-block",
margin: "15px"
};
return(
<div style={cardStyle}>
<PlayerImage imgUrl={this.props.imgUrl}/>
<Label playerName={this.props.playerName}/>
</div>
);
}
}
ReactDOM.render(
<div>
<Card imgUrl="https://imgur.com/SUbruAW.png" playerName="M. Salah"/>
</div>,
destination
);
</script>
</body>
</html>

This renders us one single player card of the incredibly talented and very handsome Mo Salah:

Image for post
Image for post

Cool.

The goal here is to figure out how to take some type of external data source, and wire up our app to generate the cards based on the external data source. Right now we’re really just hard-coding the data into the app, and that’s not going to cut it for building larger and more interesting applications. We need to be able to work with data from APIs. So in this “STEP 6” we’ll take a baby-step towards that goal.

The first thing we’ll do is assign the Card element that we are rending in our HTML div to a variable.

THIS

var card = <Card imgUrl="https://imgur.com/SUbruAW.png" playerName="M. Salah"/>

ReactDOM.render(
<div>
{card}
</div>,
destination
);

INSTEAD OF THIS:

ReactDOM.render(
<div>
<Card imgUrl="https://imgur.com/SUbruAW.png" playerName="M. Salah"/>
</div>,
destination
);

Save and refresh your page to make sure Mo Salah is still calmly celebrating a goal.

Now we’ll pull this all out into a function:

function showCards(order) {
var player_names = ["M. Salah", "E. Hazard", "R. Sterling", "S. Mane", "A. Robertson"]
var player_links = ["https://imgur.com/SUbruAW.png", "https://imgur.com/nBNG4wI.png", "https://imgur.com/pnVajXW.png", "https://imgur.com/0b6NIeE.png", "https://imgur.com/FDOwiqr.png"]
return <Card imgUrl={player_links[order]} playerName={player_names[order]}/>
}

And then in order ReactDOM.render statement:

ReactDOM.render(
<div>
{showCards(0)}
{showCards(1)}
{showCards(2)}
{showCards(3)}
{showCards(4)}
</div>,
destination
);

save, refresh your page, annnnnd:

Image for post
Image for post

Beautiful, hermosa, belle!

Now another way to handle this is to use a for loop to loop through the length of your player list and URL list and automatically create the card components for each player:

var player_names = ["M. Salah", "E. Hazard", "R. Sterling", "S. Mane", "A. Robertson"];
var player_links = ["https://imgur.com/SUbruAW.png", "https://imgur.com/nBNG4wI.png", "https://imgur.com/pnVajXW.png", "https://imgur.com/0b6NIeE.png", "https://imgur.com/FDOwiqr.png"];
var renderData = [];for (var i = 0; i < player_names.length;i++) {
renderData.push(<Card imgUrl={player_links[i]} playerName={player_names[i]}/>);
}
ReactDOM.render(
<div>
{renderData}
</div>,
destination
);

Wunderbar! Merveilleuse!

If you look at your console, though, you’ll see your player cards but you’ll see this error:

Image for post
Image for post

(Video at current time)

React wants us to provide a key to help uniquely identify the value in arrays. So it’s asking for key-value pairs instead of just values.

{key: value, key: value} vs [value, value]

We’ll modify our code with the following:

key={player_names[i]}

And sure enough, the error message disappears:

Image for post
Image for post

Well, that’s it for now. Thinking about returning at a later point to build these player cards out and add statistics and such. If you enjoyed the tutorial and would like to see an expansion, please leave a message in the comments. It’s more fun building something for friends interested in the content, so let me know!

Hope you learned something new and had a little bit of fun along the way.

Cheers,

David

Written by

Documentation and tutorials on Python, Programming, and Data Analysis. FPL Addict. Occasionally writing about biohacking, PMing, and food.

Get the Medium app