Skip to content

Instantly share code, notes, and snippets.

@timothypage
Last active October 16, 2017 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timothypage/5b89cdfa4522a573091ab97fbac496ba to your computer and use it in GitHub Desktop.
Save timothypage/5b89cdfa4522a573091ab97fbac496ba to your computer and use it in GitHub Desktop.

Intro To React

$ npm install -g create-react-app
$ create-react-app counter

delete everything except for index.js, registerServiceWorker.js

create components/ folder

create App.js

const App = () => <h1>Counter App</h1>

export default App
  • EXPLAIN functional components and JSX

change import in index.js for App

show live reload

ADD components/Counter.js

import React from 'react'

export default class Counter extends React.Component {
  
}
  • EXPLAIN class syntax
  • EXPLAIN export import syntax

add render() method

render () {
  return (
    <div>
      <p>Count: 0</p>
      <button>Increment</button>
    </div>
  ) 
}
  • EXPLAIN top level <div> wrapper
  • EXPLAIN using class syntax for state use

ADD onClick={this.handleIncrement} to <button>

ADD handleIncrement () {console.log('Increment')}

SHOW console

ADD constructor () method

constructor (props) {
  super(props)
  
  this.handleIncrement = this.handleIncrement.bind(this)
  
  this.state = {count: 0}
  
}
  • EXPLAIN constructor syntax and super, binding of event handlers ADD body to handleIncrement ()
handleIncrement () {
  this.setState((prevState) => ({count: prevState.count + 1})
}
render () {
  return (
    <div>
      <p>Count: {this.state.count}</p>
      <button onClick={this.handleIncrement}>Increment</button>
    </div>
  )
}

SHOW increment working

Multiple Counters

What if we wanted to have more than one counter?

Need to keep "counters" state somewhere, probably in App

If we need to keep track of state, we should use class syntax

-> Convert App to class syntax

Add counters to state in constructor

constructor (props) {
  super(props)
  
  this.state = {
    counters = [{id: 0}]
  }
}

ADD <button> to render

<button onClick={this.handleAddCounter}>Add Counter</button>

ADD handleAddCounter method and binding to this in constructor

handleAddCounter () {
  this.setState(prevState => ({
    counters: prevState.counters.concat({id: prevState.counters.length})
  })
}

render based on state.counters

{this.state.counters.map(counter => <Counter key={counter.id} />)}
  • EXPLAIN Array::concat vs Array::push
  • EXPLAIN ids and key prop

Counters with names

So, maybe we would want to set a name for a Counter...

ADD <input> to App#render

<label htmlFor="newCounterName">New Counter Name</label>
<br />
<input type="text"
       value={this.state.newCounterName}
       onChange={this.handleNewCounterNameChange} />
  • EXPLAIN consequences of using react state for inputs

ADD this.handleNewCounterNameChange = this.handleNewCounterNameChange.bind(this) to constructor

ADD newCounterName: "" to initialState

ADD name: "Counter" to initial counter in array

ADD handleNewCounterNameChange

handleNewCounterNameChange (event) {
   this.setState({
     newCounterName: event.target.value
   })

ADD name prop to Counter in App

ADD name display to Counter component

SHOW name is rendered on add

But, name persists in text box

ADD newCounterName: "" to handleAddCounter setState

Extra Credit: Add on Enter keypress

ADD onKeyPress={this.handleNewCounterNameKeyPress} to <input>

ADD #handleNewCounterNameKeyPress

handleNewCounterNameKeyPress (event) {
  if(event.key === "Enter") {
    this.handleAddCounter()
  }
}

Extra Credit: Form error handling

We don't want to create a counter if the form is blank

ADD error: false to initial state

ADD style={{border: this.state.error ? "5px solid red" : "1px solid"}} to input

ADD error handling to handleAddCounter

handleAddCounter () {
  if(this.state.newCounterName === "") {
    this.setState({error: true})
    return
  }
  
  ...
}

ADD error: false to handleNewCounterNameChange

Extra Credit: Set State outside of an event

CHANGE <h1> in app to "Visits"

add setInterval to Counter constructor

constructor (props) {
  ...
  
  if(this.props.name === "Your Mom") {
    this.incrementInterval = setInterval(this.handleIncrement, 400)
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment