Skip to content

Instantly share code, notes, and snippets.

@chadfurman
Last active March 13, 2017 05:35
Show Gist options
  • Save chadfurman/0476c36597d550f5487304d999d8fc44 to your computer and use it in GitHub Desktop.
Save chadfurman/0476c36597d550f5487304d999d8fc44 to your computer and use it in GitHub Desktop.
Full-Stack React Notes: 3/6-3/13

Intro

  • Brian Holt -- worked at Netflix, Reddit, wrote Reddit's first React code
  • btholt.github.io/complete-intro-to-react-v1
  • nho.lt/react

Yarn

  • Be above node 4 -- he's on 6+
  • nvm is a useful tool
  • What is yarn? yarn came out recently, it's new / shiny / fun, it replaces npm, it's by facebook
  • npm install --save react vs yarn add react
  • npm installs are not "deterministic" -- they don't always endup in the same state
  • yarn uses a lockfile, you always end up with the same dependencies
  • yarn is faster
  • Note I was getting errors installing with yarn until I removed the npm install'd version and ran the following:
wget https://yarnpkg.com/install.sh
chmod +x install.sh
./install.sh --nightly

Using yarn

  • installing 800 dependencies in ~11 seconds
  • lots of alpha/beta versions, ignore the warnings
  • yarn installs all of your dependencies in a flat structure and "links" them together
  • NPM would build a giant tree with node modules -> node modules -> node modules etc
  • there's a yarn init
  • yarn upgrade-interactive
  • yarn global add _____

Understanding React

  • You don't need any tooling to write react
  • We will start with zero tooling
  • React is just a library with function calls that produces markup
  • No ES6, no JSX, just bare-bones react
  • Why is react useful?
    • If you're coming from jquery, angular, knockout, ember, etc...
    • React is "just a view library"
    • React is just the "view" in MVC
    • This is an over-simplification
  • MVC in the front-end?
    • Models / Views / Controllers
    • Backbone is where this started in the front-end
      • Models / Views in the front-end aren't quite "true"
      • Things get really blurry with what-goes-where
      • hard to debug/read
    • Angular / Ember focuses more on UI-type concerns
      • I have this piece of code that needs to do something
      • where does it go? This is still a thing.
      • This is a small problem while you write it, and a big problem when you need to debug
      • Where is the JS? Is it in the directive? Service? Scope / Template? etc.
    • React threw out "MVC"
  • Best pattern for UI -- request/response cycle
    • click a button, get a response, etc.
  • Squish together all the CSS/JS/HTML in a single "component"
    • By knowing what the problem is, we know where the code starts.
  • Don't mix libraries. If you're using React, go with React. Don't have a hybrid in production.

My First Component

  • index.html
  • div w/ id="app" where react hooks to dom
  • text inside id="app" div will show until react renders
  • need to load both react/dist/react.js and react-dom/dist/react-dom.js
    • React is the library for expressing UIs
    • react-dom is the renderer
    • react-native, aframe-react, react3 are all renderers
    • we will be focusing on react-dom as our "glue layer"
  • Now we can write our JS -- let's just put it right in html for fun
  • React.createClass({ renderer: function() { return ( ... ) } });
    • You must have the parenthesis around your return value.
var MyTitle = React.createClass({
  render: function() {
    return (
      React.DOM.div(null,
        React.DOM.h1({style: {color: this.props.color}}, this.props.title)
      )
    )
  }
})

var MyTitleFactory = React.createFactory(MyTitle)

var MyFirstComponent = React.createClass({
  render: function() {
    return (
      React.DOM.div(null, // null is the attributes, classname / id / empty object / etc
        MyTitleFactory({ color: 'peru', title: 'props are the best'}),
        MyTitleFactory({ color: 'mediumaquamarine', title: 'strings'}),
        MyTitleFactory({ color: 'blanchedalmond', title: 'and stuff'}),
        MyTitleFactory({ color: 'rebeccapurple', title: 'are fun'})
      )
    )
  }
})

ReactDOM.render(React.createElement(MyFirstComponent), document.getElementById('app'))

createClass vs createElement

  • createClass returns a "blueprint" that we can use to stamp out elements
  • createElement is one stamp
  • ReactDOM.render(React.createElement(MyFirstComponent), document.getElementById('app'))

My Second Component

  • Every component must have a render function
  • The render function must return markup
  • The render method must be a "pure" function
    • It should not modify any state
    • it should not have any lasting state
    • Every time you render it, you should get the same response as you did the first time
  • We won't be using semi-colons, and will be using standard linter
var MyTitle = React.createClass({
  render: function() {
    return (
      React.DOM.div(null,
        React.DOM.h1(null, "Check out this component!")
      )
    )
  }
});

var MyFirstComponent = React.createClass({
  render: function() {
    return (
      React.DOM.div(null, // null is the attributes, classname / id / empty object / etc
        React.createElement(MyTitle),
        React.createElement(MyTitle),
        React.createElement(MyTitle),
        React.createElement(MyTitle)
      )
    )
  }
});

ReactDOM.render(React.createElement(MyFirstComponent), document.getElementById('app'));

Factories and Props

  • var MyTitleFactory = React.createFactory(MyTitle)
  • MyTitleFactory(null) is now the same as React.createElement(MyTitle)
  • Now, we can do MyTitleFactory({ title: "Some prop"}) and pass in a title property, for example
  • Properties are read only
  • in our MyTitle component, we can now do this.props.title and get the value of the prop for the component
  • We can also pass in colors and use them as a style
    • styles are a little different
    • React.DOM.h1({styel: {color: this.props.color}}
var MyTitle = React.createClass({
  render: function() {
    return (
      React.DOM.div(null,
        React.DOM.h1({style: {color: this.props.color}}, this.props.title)
      )
    )
  }
})

var MyTitleFactory = React.createFactory(MyTitle)

var MyFirstComponent = React.createClass({
  render: function() {
    return (
      React.DOM.div(null, // null is the attributes, classname / id / empty object / etc
        MyTitleFactory({ color: 'peru', title: 'props are the best'}),
        MyTitleFactory({ color: 'mediumaquamarine', title: 'strings'}),
        MyTitleFactory({ color: 'darkvioletred', title: 'and stuff'}),
        MyTitleFactory({ color: 'rebecapurple', title: 'are fun'})
      )
    )
  }
})

ReactDOM.render(React.createElement(MyFirstComponent), document.getElementById('app'))

Using Standard

  • non-configurable linter
  • prevents bike-shedding about JS style
  • outlaws semicolons (there's also semi-standard)
  • standard --fix is pretty helpful
  • standard is just wrapping eslint with pre-set configuration
  • to make lots of the globals not be "undefined", we use /* global React ReactDOM */

NPM Scripts

  • easy way of running commands with lots of arguments
  • Just remember the name of the command and npm will do it for you
  • package.json
{
  scripts: {
	  lint: "standard"
  }
}
  • Not necessarily useful with standard but much more useful with some of the more complicated build commands
  • gulp and grunt are still useful tools! Don't try to replace them entirely :)

Webpack & ES6 Modules

  • Webpack is in beta only because its docs aren't done
  • Webpack is a great tool, takes all modules you create and puts it in one file to send-down to client
  • Also has "loaders" -- does lots of other stuff this way
  • We'll be using webpack2
  • this allows us to do things like import React from 'react' -- es6 modules
  • also, export default Mytitle
  • CommonJS: var React = require('react');
  • We're not quite using webpack yet but will in a second.
/* ClientApp.js */
import React from 'react'
import ReactDOM from 'react-dom'
import MyTitle from './MyTitle'

var MyTitleFactory = React.createFactory(MyTitle)

var MyFirstComponent = React.createClass({
  render: function () {
    return (
      React.DOM.div(null, // null is the attributes, classname / id / empty object / etc
        MyTitleFactory({color: 'peru', title: 'props are the best'}),
        MyTitleFactory({color: 'mediumaquamarine', title: 'strings'}),
        MyTitleFactory({color: 'blanchedalmond', title: 'and stuff'}),
        MyTitleFactory({color: 'rebeccapurple', title: 'are fun'})
      )
    )
  }
})

ReactDOM.render(React.createElement(MyFirstComponent), document.getElementById('app'))
/* MyTitle.js */
import React from 'react'

var MyTitle = React.createClass({
  render: function () {
    return (
      React.DOM.div(null,
        React.DOM.h1({style: {color: this.props.color}}, this.props.title)
      )
    )
  }
})

export default MyTitle

Bundling with Webpack

  • Need to install webpack first
  • sudo npm install -g [email protected]
  • webpack
  • webpack js/ClientApp.js public/bundle.js
    • This was what he suggested
    • I ended up using webpack js/ClientApp.js which creates the bundle by default
    • this gives us the unminified, uncompressed version, not for production
    • NODE_ENV=production webpack -p js/ClientApp.js will be much smaller
    • we want the debug version for develpoment to have better error messages
  • edit index.html:
    • just include public/bundle.js -- don't need to pull in other files
  • I had to add "propTypes" to my createClass, so it looks like as follows:
/* js/MyTitle.js */
import React from 'react'

var MyTitle = React.createClass({
  propTypes: {
    color: React.PropTypes.string.isRequired,
    title: React.PropTypes.string.isRequired
  },

  render: function () {
    return (
      React.DOM.div(null,
        React.DOM.h1({style: {color: this.props.color}}, this.props.title)
      )
    )
  }
})

export default MyTitle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment