Intro to React - Featuring Modern JavaScript

Post on 16-Jul-2015

175 views 8 download

Transcript of Intro to React - Featuring Modern JavaScript

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