intro to react - featuring modern javascript
TRANSCRIPT
Intro to ReactFeaturing Modern JavaScript
By / & / Brian Scaturro @scaturr Jason Sich @jasich
ReactA JavaScript library for building user interfaces
http://facebook.github.io/react/And to steal bullet point's from React's website:
JUST THE UILots of people use React as the V in MVC. Since React
makes no assumptions about the rest of yourtechnology stack, it's easy to try it out on a small
feature in an existing project.
Virtual DomReact uses a virtual DOM diff implementation forultra-high performance. It can also render on theserver using Node.js — no heavy browser DOM
required.
Data FlowReact implements one-way reactive data flow which
reduces boilerplate and is easier to reason aboutthan traditional data binding.
Components FTWIt's about separation of (application) concerns.
Thinking in components
Components as state machinesComponents 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 ComponentsSo like....I've heard React is all about inline styles.
Whhuuuutttt?
Well.....yes and noStyles 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. Statechange = style change.
And it's still HTMLAt the end of the day, the end result is an HTML document. HTML
documents can have links to stylesheets.
Using ES6 in ReactIntroducing React with idiomatic ES6.
React v0.13.0 allows for implementing components using JavaScriptclasses
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̀ keywordlet choices = this.props.choices;
// arrow and map functionlet 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 ApplicationsWith Flux
Immutability! Unidirectional data flow!
The dispatcher, stores and views are independentnodes 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 actionsStores 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 dataIn 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 toanother object changing, which could also trigger
more updates. As applications grew, these cascadingupdates made it very difficult to predict what wouldchange 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 ToolsCurrently 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 workflow1. Transpile ES6 to ES52. Compile JSX to JavaScript3. Launch or reload a browser4. Compile SCSS, Jade, whatever5. 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 usefulbabelbrowserifygulpwebpack
Testing With JestHey! It's worth a mention.
Oh... another Jasmine style testingframework?
The Angular team built karmaThe React team built Jest
OK
So... this one does what?Mock by defaultFake 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 testsIt requires the babel-jest package (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" ]}
MixinsReact doesn't really go for subclassing components, but it does provide
support for the timeless JavaScript classic, the mixin.
Quick reviewA mixin is an object that typically gets merged into the prototype ofanother 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.bind( this.getDomNode().addEventListener('mouseout', this._onMouseOut.bind( }, componentWillUnmount() { this.getDomNode().removeEventListener('mouseover', this._onMouseOver.bind( this.getDomNode().removeEventListener('mouseout', this._onMouseOut.bind( }, _onMouseOver() {
this.setState({hovered: true});
The component* life cycle events can be duplicated. React allowsmultiple 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 mixinsNote the React.createClass call. Unfortunately ES6 does not have an
official mixin mechanism, so we have to use this means of creating acomponent.
React On The Server And ClientIsomorphic 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 Reacthttps://github.com/reactjs/react-future
ExamplesA React app using webpack and friendshttps://github.com/jasich/meal-planner
A React app using browserify and friendshttps://github.com/brianium/plan-and-eat