Intro to React

Props and State

Objectives

  • Setup tools for React dev
  • Learn what a component is & component architecture
  • Define JSX
  • Understand props and how to use them
  • Learn what state is
  • Learn how to pass state down as props

create-react-app

React can be imported and run in the browser via the <script> tag!

However, most people run React from Node.js with a webpack server, which create-react-app sets up for you.

prettier

A super helpful tool for writing React code is prettier. This tool automatically formats your JavaScript code and can make writing React code easier.

You can then configure your editor to automatically format the code for you.

Components

One of the key concepts in React is the use of components.  

A component is a reusable element that can be displayed on the web page, consisting of markup (HTML), style (CSS), behavior (JavaScript).

When you use React, you are ultimately creating components that are modular enough to be reused many times and potentially in many places in your application

Web app example: GitHub

GitHub with components

JSX

JSX allows you to write HTML in your JavaScript.

Built-in DOM elements are lowercase, and custom components are uppercase:

<div id="container" > 
  <MainHeader>
    <nav>
     <Navbar />
    </nav>
  </MainHeader>
  <MainContent />
</div>

First Component

We use ES6 Class Syntax to create our first React component

import React, { Component } from 'react';

class MyFirstComponent extends Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <h1>Hello World</h1>;
  }
}

export default MyFirstComponent;

Props

Any component that you create can accept props, which are data attributes, from a parent component.

Props are read only: they cannot be changed from within the component itself. In other words, props are immutable.

import React, { Component } from 'react';

class BusinessCard extends Component {
  render() {
    return (
      <div>
        <h2> {this.props.name} </h2>
        <h3> {this.props.title} </h3>
        {this.props.links.map(link => <li>{link}</li>)}
      </div>
    );
  }
}

class MyProfile extends Component {
  render() {
    return (
      <div>
        <h1> Profile </h1>
        <hr />
        <BusinessCard
          name="Michael Hueter"
          title="Lead Instructor"
          links={[
            'http://github.com/hueter',
            'http://linkedin.com/in/michael-hueter'
          ]}
        />
      </div>
    );
  }
}

export default MyProfile;

Props

Example

Props Exercise

  1. Make a ListItem component that renders an <li> with a name passed from props
  2. Make a List component which is a parent that renders 10 ListItems based on the array below:

const names = [
  'Ernesto Garner',
  'Mitchell Rice',
  'Travis Freeman',
  'Jenny Lane',
  'Viola Baldwin',
  'Donna Alvarado',
  'Kelly Guzman',
  'Kirk Paul',
  'Edna Jordan',
  'Juana Bates'
];

Props Solution

import React, { Component } from 'react';

class ListItem extends Component {
  render() {
    return <li>{this.props.name}</li>;
  }
}

const names = [
  'Ernesto Garner',
  'Mitchell Rice',
  'Travis Freeman',
  'Jenny Lane',
  'Viola Baldwin',
  'Donna Alvarado',
  'Kelly Guzman',
  'Kirk Paul',
  'Edna Jordan',
  'Juana Bates'
];

class MyList extends Component {
  render() {
    return names.map(name => <ListItem name={name} />);
  }
}

export default MyList;

PropTypes

import PropTypes from 'prop-types';

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

Greeting.propTypes = {
  name: PropTypes.string
};

One way to describe the props that a component accepts is PropTypes. Using PropTypes also has the added benefit of doing some basic type checking (e.g. "I expect this prop to be a string").

Default Props

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

// Specifies the default values for props:
Greeting.defaultProps = {
  name: 'Stranger'
};

We can utilize defaultProps if we're not sure if the parent component is going to pass anything down!

State

When building dynamic web applications, we often want to be able to change our data.

In React, we store dynamic data as state in the app.

class Greeting extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Michael'
    };
  }
  render() {
    return <h1>Hello, {this.state.name}</h1>;
  }
}

Changing State

import React, { Component } from 'react';

export default class Greeting extends Component {
  state = {
    name: 'Michael'
  };

  changeName = () => {
    const newName = this.state.name === 'Michael' ? 'Not Michael' : 'Michael';
    this.setState({ name: newName });
  };

  render() {
    return (
      <div>
        <h2>Hello, {this.state.name}!</h2>
        <button onClick={this.changeName}>
          Change my name, change my name
        </button>
      </div>
    );
  }
}

Important State Concepts

1. State should be owned by only one component. This simple rules makes React components much easier to debug and understand.

 

2. When state is changed inside of a component, the render method will eventually be invoked by React. The key word here is eventually. Changes to state do not always show up right away (in practice they happen very quickly).

Passing State Down as Props (1 of 2)

import React, { Component } from "react";
import Coin from "./Coin";

class CoinGame extends Component {
  state = {
    flipValue: Math.random()
  };

  flip = () => {
    this.setState({ 
      flipValue: Math.random() 
    });
  };

  render() {
    return (
      <div>
        <Coin side={this.state.flipValue} />
        <button onClick={this.flip}>Flip!</button>
      </div>
    );
  }
}

export default CoinGame;

Passing State Down as Props (2 of 2)

import React, { Component } from "react";
import heads from "./heads.jpg";
import tails from "./tails.jpg";

class Coin extends Component {
  render() {
    const coinObj = { heads, tails };
    const key = this.props.side < 0.5 
                ? "heads" 
                : "tails";
    return (
      <div>
        <img src={coinObj[key]} />
        <p>The coin came up {key}!</p>
      </div>
    );
  }
}

export default Coin;

State Example

State Exercise

1. Build a stateful component called MoodChanger that cycles through an array of moods by clicking a button, and renders an ASCII emoji. Starter code:

class MoodChanger extends Component {
  state = {
    currentMood: 'happy',
    face: ':-)',
    currentMoodIdx: 0,
    moods: ['happy', 'sad', 'angry', 'neutral']
  };

  changeMood = e => {
    // fill me in
  };

  render() {
    return (
      <div>
        <h1>{this.state.face}</h1>
        <button onClick={this.changeMood}> Change Mood </button>
      </div>
    );
  }
}

State Exercise Solution

Check out the completed code on GitHub

Resources

Made with Slides.com