Intro to React Featuring Modern JavaScript By / & /Brian Scaturro @scaturr Jason Sich @jasich
React A JavaScript library for building user interfaces http://facebook.github.io/react/ And to steal bullet point's from React's website:
JUST THE UI Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it's easy to try it out on a small feature in an existing project.
Virtual Dom React uses a virtual DOM diff implementation for ultra-high performance. It can also render on the server using Node.js — no heavy browser DOM required.
Data Flow React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding.
Components FTW It's about separation of (application) concerns.
Thinking in components
Components as state machines Components have various states, and we render different views for different states.
Components are composable render() { return <div> <MealList meals={this.state.meals} /> <ChoiceFilter /> <ChoiceList allChoices={this.state.allChoices} / > </div> } State can live at the top and be passed down via properties.
Styling Components So like....I've heard React is all about inline styles. Whhuuuutttt?
Well.....yes and no Styles are really just state too. const dropState = this.getDropState('choice'); let styles = {}; if (dropState.isHovering) { //yup that's state styles.backgroundColor = '#FFD34E'; } if (this.props.selection) { //yeah that's state too styles.backgroundImage = 'url(' + this.props.selection.picUrl + } The end result is that styles benefit from reactive goodness. State change = style change.
And it's still HTML At the end of the day, the end result is an HTML document. HTML documents can have links to stylesheets.
Using ES6 in React Introducing React with idiomatic ES6. React v0.13.0 allows for implementing components using JavaScript classes JSX transformers allow for transpiling of ES6 to ES5 code
Classes and modules example import React from 'react'; class ChoiceRow extends React.Component { } export default ChoiceRow;
ES6 in action // `let` keyword let choices = this.props.choices; // arrow and map function let children = choices.map(c => (<Choice item={c} />)); return <div className="row"> {children} </div>
proxies, promises, let, const, generators, etc... Bottomline, the next evolution of JavaScript gives us a lot of cool stuff, and it would be really nice to use today.
Unfortunately... ES6 is not very well supported in most browsers.
There is hope! A lot of really smart people are working towards making ES6 usable today.
Perceived (and maybe some actual) Downsides
Synthetic events
Inline styles
Too much rendering?
Lots of code
Building React Applications With Flux Immutability! Unidirectional data flow! The dispatcher, stores and views are independent nodes with distinct inputs and outputs. The actions are simple objects containing the new data. https://facebook.github.io/flux/docs/overview.html#content
MVC doesn't scale
Views create new actions
Perhaps with a search form? class ChoiceFilter extends React.Component { render() { return <input type="text" onChange={this._onChange} /> } _onChange(event) { ChoiceActions.filter(event.target.value); //create an action! } } ChoiceActions.js
Stores respond to actions Stores respond to actions, and emit change events. const store = new ChoiceStore(); AppDispatcher.register(function (action) { switch(action.actionType) { case ChoiceConstants.CHOICE_FILTER: store.filter(action.search); store.emit(CHANGE_EVENT); //there is a change! break; default: break; } }); export default store; //yup that's a single store
Views ASK for data In a departure from the prevalent "two-way binding" sorcery, views listen for changes and ask for data.
An example let getState = () => { allChoices: ChoiceStore.getChoices() //asking for data } class MealPlanner extends React.Component { constructor() { this.state = getState(); //initial state } componentWillMount() { ChoiceStore.addChangeListener(this._onChange.bind(this)); //listen } _onChange() { this.setState(getState()); //there was a change - ask for data
But why?!?!?! We found that two-way data bindings led to cascading updates, where changing one object led to another object changing, which could also trigger more updates. As applications grew, these cascading updates made it very difficult to predict what would change as the result of one user interaction. When updates can only change data within a single round, the system as a whole becomes more predictable. https://facebook.github.io/flux/docs/overview.html#content
The Tools Currently we have to jump through hoops to transpile ES6 to ES5, and use handy things like JSX. It's nice necessary to have tools to do it for us
What we want out of a workflow 1. Transpile ES6 to ES5 2. Compile JSX to JavaScript 3. Launch or reload a browser 4. Compile SCSS, Jade, whatever 5. Do this all when we change a file The less we have to focus on building and running, the better
There are a lot of tools out there, here are a few we find useful babel browserify gulp webpack
Testing With Jest Hey! It's worth a mention.
Oh... another Jasmine style testing framework? The Angular team built karma The React team built Jest OK
So... this one does what? Mock by default Fake DOM via jsdom Some new things, it's cool (but so is anything that lets you test your code)
In the land of React jest.dontMock('../ChoiceStore'); jest.dontMock('../../data.json'); describe('ChoiceStore', function () { let ChoiceStore; let data; beforeEach(function () { ChoiceStore = require('../ChoiceStore'); data = require('../../data.json'); }); describe('.getChoices()', function () { it('should return all meal options by default', function () let choices = ChoiceStore.getChoices();
A note on ES6 in tests It requires the babel-jestpackage (or a similar transpile hook), and a little tweak to your package.json file. "jest": { "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "testFileExtensions": [ "js" ], "moduleFileExtensions": [ "js" ] }
Mixins React doesn't really go for subclassing components, but it does provide support for the timeless JavaScript classic, the mixin.
Quick review A mixin is an object that typically gets merged into the prototype of another object - effectively adding that behavior to instances of the target object.
Add hover functionality? let HoverMixin = { componentWillMount() { this.state = this.state || {}; this.state.hovered = false; }, componentDidMount() { this.getDomNode().addEventListener('mouseover', this._onMouseOver.bi this.getDomNode().addEventListener('mouseout', this._onMouseOut.bind }, componentWillUnmount() { this.getDomNode().removeEventListener('mouseover', this._onMouseOver this.getDomNode().removeEventListener('mouseout', this._onMouseOut.b }, _onMouseOver() { this.setState({hovered: true}); The component* life cycle events can be duplicated. React allows multiple definitions for those when creating mixins.
Do the mixing import HoverMixin from 'HoverMixin'; import React from 'react'; const MyComponent = React.createClass({ mixins: [HoverMixin] }); export default MyComponent;
The struggle of mixins Note the React.createClasscall. Unfortunately ES6 does not have an official mixin mechanism, so we have to use this means of creating a component.
React On The Server And Client Isomorphic JavaScript applications can run on both the server and client. React has a node module which allows it to be rendered on the server.
Future React https://github.com/reactjs/react-future
Examples A React app using webpack and friends https://github.com/jasich/meal-planner A React app using browserify and friends https://github.com/brianium/plan-and-eat

Intro to React - Featuring Modern JavaScript