Bootcamp Notes – Day 7 (Mon) – React: Week 3 – React Router and Single Page Applications

React Router and Single Page Applications

JavaScript: Object Destructuring

 

Object Destructuring/Destructuring Syntax

We will be learning something in JavaScript called object destructuring.

The destructuring assignment syntax was introduced in ES6 and gives us a shortcut for accessing properties inside objects or items inside arrays and putting them inside new variables. We will first look at the basic destructuring assignment syntax, then we will look at how it works with function parameters.

Pull up your developers console in your browser.

First let’s consider an object with three properties. We will create a hotel object with an id, city and name properties. Now let us say that we needed to pull out each of these properties into a new variable. This would be the old way to do it and if you type in each of these variables into the console. You can see they grab the values from the object properties, as you expect.

Now refresh your page F5 to clear out the console and variables. Now the new way using the hotel object, using the structuring assignment syntax, specifically object destructuring. It is going to look funny using the curly braces on the left side of the assignment and now you can check what is inside in each of these variables. You see that this worked exactly the same as  doing it the old way that was shown before above, but it is a lot faster.

We can do the same thing, when we pass an object into a function. Let see how that is done. We will clear our console, but not refresh.

We will write a function called logHotelInfo1 and it will take as it parameter a hotel object like we created previously. This will be an example of not using object destructuring. So we are going to pass in the entire hotel object. Let us say that inside this function, we want to access the properties of the hotel object. To do this without object destructuring look at our example.

You can see from the example above, that it worked from this console log.

Destructuring with functions

Now see how it can be done with object destructuring. We will write a  new function logHotelInfo2 and for its parameter list instead of passing in the hotel object. We are going to pass in a pair of curly braces that contain the words: {id, name, city}. Now what this does is, it tells the function an object is going to be passed into it and will have these properties id, name, city It could have more properties than these, but these three id, name, city are the ones that we want from this object. Then inside the function, variables will automatically  be created using using these three property names and their values will be taken from the corresponding object properties of whatever object is passed in. Basically, it is doing exactly what we did in the first function logHotelInfo1 but this is a shortcut way of writing it. Then we can console.log the same line and call it by passing in the same hotel object. An you can see by the example below, it was a lot faster to write and does the same thing.

So when you see curly braces used on the left side of the assignment operator or see curly braces being used like this, in the parameter list of a function definition. Then that is your clue that this structuring is taking place and this is how you read it. It is saying here is an object look inside it for these property names then assign their values to variables using those property names. This is not the only way that object destructuring or desctructuring assignment syntax can be used. There are other ways to use the object destructuring syntax and there’s a a destructuring syntax for arrays as well.


Presentational and Container Components

In React there is no formal classification of presentational versus container components. This is conceptual terminology that has risen to describe how certain components behave. Container components are responsible for fetching and managing state data and passing that state data to child components to be rendered. Container components don’t do any rendering themselves. That means that not all react components are required to render a part of the Ui. Container components are focused on handling management of data instead.

Presentational Components on the other hand are stricly focused on the UI with styles, colors, positioning, things of that nature. Thus presentational components will typically not hold any state data and only use the data handed down to them as props. If they do hold any state data it would typically be just a little bit of data about the current state of the Ui , such as the window size or if a model is open. Once again this is not a formal classification in React. You will find people use other terminology that refers to the same basic concept. Components do not all have to be strictly presentational or strictly container in purpose. However it is often a useful way to organize components.


Presentational and Container Components

Refer to code below for this part. 4 files have changed. Complex stuff:

MainComponent.js

import React, { Component } from ‘react’;
import { Navbar, NavbarBrand } from ‘reactstrap’;
import Directory from ‘./DirectoryComponent’;
import CampsiteInfo from ‘./CampsiteInfoComponent’;
import { CAMPSITES } from ‘../shared/campsites’;
class Main extends Component {
    constructor(props) {
        super(props);
        this.state = {
            campsites: CAMPSITES,
            selectedCampsite: null
        };
    }
    onCampsiteSelect(campsiteId) {
        this.setState({selectedCampsite: campsiteId});
    }
    render() {
        return (
            <div>
                <Navbar dark color=”primary”>
                    <div className=”container”>
                        <NavbarBrand href=”/”>NuCamp</NavbarBrand>
                    </div>
                </Navbar>
                <Directory campsites={this.state.campsites} onClick={campsiteId => this.onCampsiteSelect(campsiteId)}/>
                <CampsiteInfo campsite={this.state.campsites.filter(campsite => campsite.id === this.state.selectedCampsite)[0]} />
            </div>
        );
    };
}
export default Main;

 App.js

import React, { Component } from ‘react’;
import Main from ‘./components/MainComponent’;
import ‘./App.css’;
class App extends Component {
    render() {
        return (
            <div className=”App”>
                <Main />
            </div>
        );
    };
}
export default App;

DirectoryComponent.js

import React, { Component } from ‘react’;
import { Card, CardImg, CardImgOverlay, CardTitle } from ‘reactstrap’;
class Directory extends Component {
  
    render() {
        const directory = this.props.campsites.map(campsite => {
            return (
                <div key={campsite.id} className=”col-md-5 m-1″>
                    <Card onClick={() => this.props.onClick(campsite.id)}>  
                        <CardImg width=”100%” src={campsite.image} alt={campsite.name} />
                        <CardImgOverlay>
                            <CardTitle>{campsite.name}</CardTitle>
                        </CardImgOverlay>
                    </Card>
                </div>
            );
        });
        return (
            <div className=”container”>
                <div className=”row”>
                    {directory}
                </div>
            </div>
        );
    }
}
export default Directory;

CampsiteInfoComponent.js

import React, { Component } from “react”;
import {
  Card,
  CardImg,
  CardImgOverlay,
  CardText,
  CardBody,
  CardTitle,
} from “reactstrap”;
class CampsiteInfo extends Component {
  renderCampsite(campsite) {
    return (
      <div className=”col-md-5 m-1″>
        <Card>
          <CardImg top src={campsite.image} alt={campsite.name} />
          <CardBody>
            <CardTitle>{campsite.name}</CardTitle>
            <CardText>{campsite.description}</CardText>
          </CardBody>
        </Card>
      </div>
    );
  }
  renderComments(comments) {
    if (comments) {
      return (
        <div className=”col-md-5 m-1″>
          <h4>Comments</h4>
          {comments.map((comment) => {
            return (
              <p key={comment.id}>
                {comment.text} <br />
                {comment.author}{” “}
                {new Intl.DateTimeFormat(“en-US”, {
                  year: “numeric”,
                  month: “short”,
                  day: “2-digit”,
                }).format(new Date(Date.parse(comment.date)))}
              </p>
            );
          })}
        </div>
      );
    }
    return <div />;
  }
  render() {
    if (this.props.campsite) {
        return (
            <div className=”container”>
                <div className=”row”>
                    {this.renderCampsite(this.props.campsite)}
                    {this.renderComments(this.props.campsite.comments)}
                </div>
            </div>
        );
    }
    return <div />;
  }
}
export default CampsiteInfo;

 

Site should still look like this after adding all your code:


Functional Components

We learned awhile back that there are two ways to define React Components:

  • Class Components
  • Function Components

We have been defining components using class components so far, but now we will look at functional components. Functional components are written just like a function as the function declaration, function expression or error function.

Typically you will only see them written as function declarations or arrow functions. Like with all components they need to have the first letter capitalized and they need to accept props as an argument.

Like class components, they will always return at least one react element, but they do not use the render method around the return and they will never have a constructor method. Another difference is that when you refer to props inside a functional component. You do not use the this keyword. The class component equivalent of this example functional component will be written like this below. These are equivalent

Along with not using the render. Functional components cannot hold state nor use something called lifecycle methods.

Note: A recent version of React(v 16.8) introduced an addition called hooks that provides ways for a functional components to access state and lifecycle methods.

We will use the established way of using class components for now.


Ok we will change our code on these two files to what is given:

DirectoryComponent.js

import React from ‘react’;
import { Card, CardImg, CardImgOverlay, CardTitle } from ‘reactstrap’;
function RenderDirectoryItem({campsite, onClick}) {
    return (
        <Card onClick={() => onClick(campsite.id)}>
            <CardImg width=”100%” src={campsite.image} alt={campsite.name} />
            <CardImgOverlay>
                <CardTitle>{campsite.name}</CardTitle>
            </CardImgOverlay>
        </Card>
    );
}
function Directory(props) {
    const directory = props.campsites.map(campsite => {
        return (
            <div key={campsite.id} className=”col-md-5 m-1″>
                <RenderDirectoryItem campsite={campsite} onClick={props.onClick} />
            </div>
        );
    });
    return (
        <div className=”container”>
            <div className=”row”>
                {directory}
            </div>
        </div>
    );
}
export default Directory;

CampsiteInfoComponent.js

import React from ‘react’;
import { Card, CardImg, CardText, CardBody, CardTitle } from ‘reactstrap’;
  function RenderCampsite({campsite}) {
    return (
      <div className=”col-md-5 m-1″>
        <Card>
          <CardImg top src={campsite.image} alt={campsite.name} />
          <CardBody>
            <CardTitle>{campsite.name}</CardTitle>
            <CardText>{campsite.description}</CardText>
          </CardBody>
        </Card>
      </div>
    );
  }
  function RenderComments({comments}) {
    if (comments) {
      return (
        <div className=”col-md-5 m-1″>
          <h4>Comments</h4>
          {comments.map((comment) => {
            return (
              <p key={comment.id}>
                {comment.text} <br />
                {comment.author}{” “}
                {new Intl.DateTimeFormat(“en-US”, {
                  year: “numeric”,
                  month: “short”,
                  day: “2-digit”,
                }).format(new Date(Date.parse(comment.date)))}
              </p>
            );
          })}
        </div>
      );
    }
    return <div />;
  }
  function CampsiteInfo(props) {
    if (props.campsite) {
        return (
            <div className=”container”>
                <div className=”row”>
                    <RenderCampsite campsite={props.campsite} />
                    <RenderComments comments={props.campsite.comments} />
                </div>
            </div>
        );
    }
    return <div />;
}
export default CampsiteInfo;

 

Site should still look like this!


Code Challenges:

Code Demo props on codepen(Example)

Code Challenge: React Components and Object Destructuring

Code Challenge: React Components and Object Destructuring (Breakdown into just Resources)

Code Function Components (Missing Lifting Up State)

React Challenge: Lifting State Up & Function Components


Additional Resources:

You May Also Like