Views and Templates


Views

We cannot keep using response.send to send a response. Ultimately, we'll want to send HTML files back to the client.

We want to have this page's HTML be different for each request. How do we do this??


Templating with React

If we want to customize what's on the page? We're going to set up a template engine with React and use that instead.

React is used on the front end of lots of sites, but it's JSX component can also be used to simply create HTML.

We need to do a couple steps to get the template engine working.


First, install express-react-views

npm install express-react-views react react-dom

Then, prepare this directory structure on your node project.

.
├── app.js
└── views
    ├── home.jsx

1 directories, 2 files

Once structure is setup, you can setup the express view engine to jsx in this manner.

const express = require('express')
const app = express();


// this line below, sets a layout look to your express project
const reactEngine = require('express-react-views').createEngine();
app.engine('jsx', reactEngine);

// this tells express where to look for the view files
app.set('views', __dirname + '/views');

// this line sets react to be the default view engine
app.set('view engine', 'jsx');

app.get('/', (req, res) => {
  // running this will let express to run home.handlebars file in your views folder
  res.render('home')
})

JSX

JSX is javascript and HTML. It looks like this:

var React = require('react');

class Home extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello</h1>
      </div>
    );
  }
}

module.exports = Home;

At first it just seems like a javascript syntax error, but what we are doing is running this file through a parser that will create HTML for us.

Everything between the return parentheses is going to be rendered into HTML.

Templating

Templating with variables means we can pass in an object to the .render function and access those variables inside the jsx template. These variables are also called context

index.js

const express = require('express')
const app = express();


// this line below, sets a layout look to your express project
const reactEngine = require('express-react-views').createEngine();
app.engine('jsx', reactEngine);

// this tells express where to look for the view files
app.set('views', __dirname + '/views');

// this line sets handlebars to be the default view engine
app.set('view engine', 'jsx');

app.get('/', (req, res) => {
  // giving home.jsx file an object/context with `name` as a property
  res.render('home', {name: "Sterling Archer"});
});

app.listen(3000);

then we need to update our home.jsx to use a templating variable.

views/home.jsx

var React = require('react');

class Home extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, { this.props.name }!</h1>
      </div>
    );
  }
}

module.exports = Home;

The JavaScript being embedded is enclosed by the { } tags.


Conditional Rendering

Sometimes we want to decide to render something based on a variable.

We can put this code directly above the return statement, or we could also write it in another function.

var React = require('react');

class Home extends React.Component {
  render() {

    let message = "welcome!";

    if( name.length > 5 ){
      messgae = "welcome! What a long name you have!";
    }

    return (
      <div>
        <h1>Hello, { this.props.name }!</h1>
        <h1>{ message }</h1>
      </div>
    );
  }
}

module.exports = Home;

Map

The ES6 array method map allows us to return an array.

We can use map to create HTML in a loop.

Say we have the following context given to our jsx template.

var context = {
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}
var React = require('react');

class Home extends React.Component {

  render() {

    const people = this.props.people.map( person => {
      return <li>{person}</li>
    });

    return (
      <div>
        <ul>
        {people}
        </ul>
      </div>
    );
  }
}

module.exports = Home;

HTML Attributes

HTML attributes in react are written without the quotes by default:

<img src={pokemon.img} />

If you need to do string interpolation, create another variable:

let formAction = '/pokemon/' + pokemon.id;
<form action={formAction}>

CSS class names are set with className instead of class

<p className="banana">yes</p>

Pairing Exercise:

Start from scratch.

Create your app

mkdir react-v
cd react-v
npm init
npm install express
npm install express-react-views react react-dom
touch index.js

Create a dummy data file:

Go to this URL: https://jsonplaceholder.typicode.com/users

Since this is just for rendering, let's just put all of this data into a file, and use require to get it.

users.js:

module.exports = // paste the contents of the file here

Require the file into your app:

index.js:

const users = require('./users.js')

Render a single user object in react

Implement an express route /firstuser - it creates an HTML page with the first user in the array users[0].

This template should display at least 2 data fields for this user.

further

Implement a route with params: /users/:id

Use :id to get the user according to it's index in the array

further

Fix the above to search through the array and get the user according to their actual id

further

Implement an express route /users - it creates an HTML page with all of the users.

This will be a <ul> with an <li> for each user.

Use the map syntax above to render the list.

This template should display at least 2 data fields for each user.

further

Display the nested pieces of data in the user objects.

note: don't use for in to display the nexted data, or any data in the user object.

results matching ""

    No results matching ""