Section 3 - React Components

Setting Up React Locally

  1. Set up a local React project with create-react-app (refer to the lecture 9). Let’s look at the files created carefully so we know what’s going on! It might be slightly overwhelming, but once you understand what’s going on, you’ll be able to write your own React code!

  1. Open src/index.js, you should see:

import React from 'react';

import ReactDOM from 'react-dom';

import './index.css';

import App from './App';

import registerServiceWorker from './registerServiceWorker';

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

registerServiceWorker();

  1. Let’s look at the code line by line!

  1. import React from 'react';

import ReactDOM from 'react-dom';

In lines 1 and 2, we are importing the React and ReactDOM libraries so that we can use them in our code. Remember ReactDOM contains the render() function that renders our JSX onto the browser.

  1. import './index.css';

In line 3, we are importing index.css so that everything in index.js is styled.

  1. import App from './App';

In line 4, we are importing a React component called App from the file App.js. The “.js” extension can be ignored in React code.

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

The imported component is rendered in line 7 in ReactDOM.render(). All React component names must start with an upper case. They can either be self-closing (i.e. in the format <ComponentName />) or have children (i.e. in the format <ComponentName> … </ComponentName>). In this case, <App /> is intended to be used as a self-closing component (more details on how to write non self-closing components later).

  1. Finally, in line 5, we imported a function registerServiceWorker and is called on line 8. It is a given function that helps you cache your files, so that when the user is offline or on slow network, they can still see the results on the screen. Note that the app won’t break if you delete these lines, it only affects the project’s performance.

import registerServiceWorker from './registerServiceWorker';

...

registerServiceWorker();

  1. Cool! Let’s next look at what’s going on in <App />! Open src/App.js, you should see:

import React, { Component } from 'react';

import logo from './logo.svg';

import './App.css';

class App extends Component {

  render() {

    return (

      <div className="App">

        <header className="App-header">

          <img src={logo} className="App-logo" alt="logo" />

          <h1 className="App-title">Welcome to React</h1>

        </header>

        <p className="App-intro">

          To get started, edit <code>src/App.js</code> and save to reload.

        </p>

      </div>

    );

  }

}

export default App;

  1. Again, let’s look at the code line by line!

import React, { Component } from 'react';

  1. First, we import the React library. It is required in any files that use JSX. Then, we import { Component }. { … } is an ES6 syntax called destructuring. It means “import the Component function that is inside the React function and store it in the variable Component”. Notice that if you delete the { Component } part, and replace the class declaration:

Class App extends Component {

}

with

Class App extends React.Component {

}

The results are identical. More information about destructuring.


  1. Let’s talk more about the class App while we’re at it! Every React component must be declared as a class. A JavaScript class is an object that contains variables and functions. More information about JavaScript classes.

  1. The App class is defined with the code class App { … }.

  1. App also inherits from the Component class with the code extends Component. Inheriting a class means our child class (App) can access all the variables and functions in the parent class (Component). Don’t worry too much about the class and extend syntax, just think of it as a format you have to follow when writing React components. In case you’re curious, here’s a good explanation.

  1. Moving on! Every React component must have a render function. Render is a  function that returns a JSX component most of the time. In our case, the App component’s render function returns the following chunk of JSX:

<div className="App">

  <header className="App-header">

    <img src={logo} className="App-logo" alt="logo" />

    <h1 className="App-title">Welcome to React</h1>

  </header>

  <p className="App-intro">

    To get started, edit <code>src/App.js</code> and save to reload.

  </p>

</div>

  1. Most of the JSX code is pretty self-explanatory. One thing to note is that to give your JSX tag a CSS class, you must give it an attribute className instead of class, since class is a reserved JavaScript keyword.

  1. After you’ve created your class, you’ll need to export it so that you can access App from another file by so:

export default App;

Again, here’s a more detailed explanation on export default if you’re curious.

  1. Finally, to wrap things up, we have:

import logo from './logo.svg';

import './App.css';

which just imports logo.svg and App.css so that we can use them in this file.

  1. That’s all you need to know to start writing React code!

What about the other files? (Optional)

At the moment, you don’t have to worry about them. But again, just in case you’re curious:

Writing Your First React Component

  1. Now that you’ve understood the basics of React, let’s write our first React component. For our first project, let’s write a grocery list.

  1. Let’s clean up App.js so that we can start fresh! First, we remove the svg and css imports. Then, we delete everything that’s inside the render function. Your code should look something like:

import React, { Component } from 'react';

class App extends Component {

  render() {

  }

}

export default App;

  1. Let’s say we want our grocery list to look something like:

        

  1. We should create one component for the header and one the list itself! In this way, our code is more modular (i.e. each file only contains code to run one aspect of the application), therefore easier to maintain.

  1. First, create a new file Header.js in the src folder. Now, try to create a React component named Header, which returns <h1>Grocery List</h1> in the render function. Remember to:
  1. Import React and React.Component
  2. Create a class Header that extends React.Component
  3. Create a render function that returns <h1>Grocery List</h1>
  4. Export default the class you created!

Answer:

import React, { Component } from 'react';

class Header extends Component {

  render(){

    return(

      <h1>Grocer List:</h1>

    )

  }

}

export default Header;

  1. Nice! Next, create another file called GroceryList.js. This time GroceryList will render:

<ol>

  <li>Bread</li>

  <li>Peanut butter</li>

  <li>Jelly</li>

</ol>

This time there’s no hint. You’re on your own!

Answer:

import React, { Component } from 'react';

export default class GroceryList extends Component {

  render(){

    return(

      <ol>

        <li>Bread</li>

        <li>Peanut butter</li>

        <li>Jelly</li>

      </ol>

    )

  }

}

Notice how this time we wrote

export default class GroceryList extends Component {

}

Instead of

class GroceryList extends Component {

}

export default GroceryList

They both work identical! The former is cleaner, while the latter allows you to make changes to the class before exporting it (e.g. when you are using React together with other libraries such as Redux or Apollo). Don’t worry about the details for now!

  1. Now that we’ve created Header.js and GroceryList.js, we have to import them into our App.js. Add the following lines to import the components we wrote:

import Header from './Header';

import GroceryList from './GroceryList';

  1. Next, render our components inside the render() function like so:

render() {

  return (

    <div className="App">

      <Header />

      <GroceryList />

    </div>

  );

}

  1. Your grocery list application should now look something like:

  1. How cool is that?

  1. There’s one problem though. Go back to GroceryList.js, look at how we hardcoded the data, and that we typed out each <li>...</li> one by one! That’s generally not a good practice, because the code is (1) not reusable and (2) repetitive. First of all, let’s pretend there’s an external data source that grocery list data like so:

const data = ["Bread", "Peanut Butter", "Jelly"]

  1. A common practice in React to render list is to use the [array].map() function. The map() function takes in a function as a parameter. That function will take in each item in the array, do some manipulation, then return a new value for each item. After a new value is calculated for each item in the array, The map() function will return a new array with all of the new values.

  1. A simple example:

var result = [1,2,3].map(function(number){

  return number * 2;

})

result is now [2,4,6]

  1. Back to our list. Since for each item in our list, we want to render a <li> … </li> tag. We should write something like:

data.map(function(item){

  Return <li>{item}</li>;

})

  1. Remember that item is a JavaScript variable. To write JavaScript inside JSX, you have to wrap it with curly brackets.

  1. That’s a bit clumsy. Let’s try the ES6 arrow function syntax. The arrow function syntax allows you to write functions:

function(x,y){

  return x + y

}

Like so:

(x,y) => x + y

  1. Now our render() function should look like:

render(){

  return(

    <ol>

      { data.map((item)=><li>{item}</li>) }

    </ol>

  )

}

Much cleaner! Take some time to read through the code. Identify which part of the code is JavaScript and which is JSX. Do you understand why the curly brackets are where they are?

  1. Now open your browser again, the app should look exactly the same, but your code is now much reusable and clean! Now you only have to change the data variable to add or remove items from the list! However, when you open the browser’s console, you should see an error like:

Warning: Each child in an array or iterator should have a unique "key" prop.

What’s going on?

Remember when I said React knows how to only re-render necessary elements? Turns out React needs us to give a unique key to each item in the list in order to efficient re-rendering, otherwise React will just re-render the whole list everytime!

  1. Let’s make up a key for each item in our list (they can be any number or string as long as they are unique for each item), like so:

const data = [{

               key: 1,

               name: "Bread"

              },

              {

                key: 2,

                name: "Peanut Butter"

              },

              {

                key: 3,

                name: "Jelly"

              }]

        

I know if feels weird to be making up keys. Know that you will never have to do that in real life because most databases can generate unique keys for you.

  1. Change our map() function like so:

data.map((item)=><li key={item.key}>{item.name}</li>)

The error should be gone!

  1. Congratulations! You’ve just written your first React components! Although the webpage isn’t entirely impressive, I hope you can start appreciating the beauty of React! I mean, look at the JSX in your App.js:

<div>

  <Header />

  <GroceryList />

</div>

How clear and concise is it?

Summary

In this section, we first spent some time looking at the code generated by create-react-app. Most importantly, we learnt that ReactDOM.render() is responsible for rendering our JSX to the browser's DOM like so:

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

<App /> contains our entire application. This is the usual practice since now we can just pass one thing to ReactDOM.render() and we will have our whole application rendered.

Next, we looked at how we can create a React component. We wrote code like this:

import React, { Component } from 'react';

class GroceryList extends Component {

  render() {

  }

}

export default GroceryList;

This is a pattern we will use over and over again, so it’s best for you to understand and memorize it. We then learnt to render list by using the map() function. Finally, we exported the file and imported it in App.js.

In the next section, we’ll explore props in React, which is a powerful way to pass data to components!

Final Code

Here is the code for this section.