React
Redux
+

An introduction
@tkssharma
Obligatory Speaker Info
Tarun Sharma

Software Engineer
at @Srijan
i teach people
On the internet.
@tkssharma
Things I Like
-
Travelling :)
-
Learning how to write better code
-
And of course, JavaScript
Know your enemy


We covered what I like...
...but...
Things DON'T I Like
-
Duplicating code
-
Writing "framework" code
-
Debugging unhelpful errors
Duplicating Code
-
Copy/Paste code Feels Bad™
-
Reusability is the key
Including, nay, especially boilerplate
When we write composable code, it allows us to write something really well once, and reuse it as often as necessary.

"DRY code is the key to a happier, healthier life."
- Craig Burton, 2016
Writing "framework" code
-
Word.JS™ code
...with a little JavaScript mixed in


angular.module( "things", [] )
.controller( "SomeController", [ "$scope", "myService",
function( $scope, myService ){
$scope.someValue = "";
$scope.errorMsg = "";
$scope.formData = {};
myService.getThings().then(function(resp){
$scope.someValue = resp.data.someValue;
}).catch(function(resp){
$scope.errorMsg = resp.data.statusText;
});
});
Almost entirely
framework
code
Debugging unhelpful errors
An actual Angular error:
angular.js:9899 Error: [ng:areq] Argument 'fn' is not a function, got Object
http://errors.angularjs.org/1.2.17/ng/areq?p0=fn&p1=not%20a%20function%2C%20got%20Object
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:78:12
at assertArg (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:1471:11)
at assertArgFn (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:1481:3)
at annotate (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:3222:5)
at Object.invoke (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:3876:21)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:5605:43
at Array.forEach (native)
at forEach (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:320:11)
at Object.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:5603:13)
at Object.invoke (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.js:3899:17)
A helpful link?

NOPE

React is a view framework, created by Facebook.
It was designed as a tool to facilitate rapid development, and deliver a high level of performance.
Hello, World
var HelloPage = React.createClass({
render: function() {
return (
<div className="jumbotron">
<div className="container">
<h1>Hello, React!</h1>
</div>
</div>
);
}
});
Register a new component
Define a render function
...
Hey! That's not JS!
That is JSX, and it's pretty great.
Meet JSX
JSX is a JS syntax extension that looks a lot like HTML.
return (
<div className="jumbotron">
<div className="container">
<h1>Hello, React!</h1>
</div>
</div>
);
return React.createElement(
"div",
{ className: "jumbotron" },
React.createElement(
"div",
{ className: "container" },
React.createElement(
"h1",
{ "class": "" },
"Hello, React!"
)
)
);
There are a few minor differences between HTML and JSX markup. However, if you understand HTML, you'll grok JSX.
It isn't really JavaScript though. Browsers won't support it natively. So it will need to be preprocessed before you serve it to a user. There are several excellent tools for this.
But... Markup in my JS!?
Isn't that the opposite of "separation of concerns?"
<div ng-controller="SomeController">
<div ng-repeat="thing in things">
<h2>
{{ thing.title | uppercase }}
</h2>
<h3>
{{ thing.subtitle | uppercase }}
</h3>
</div>
</div>
angular.module('app')
.controller('SomeController',
function($scope, someService){
$scope.things = [ ... ]
});
Consider:
Is there really any difference between having JavaScript in your markup and having markup in your JavaScript?
React acknowledges that the view model and the template are tightly coupled, and embraces it.
Cohesion
Everything about a component is in one place, including the template.
var HelloPage = React.createClass({
someMethod: function(){
/* do some stuff here */
},
render: function() {
return (
<div className="jumbotron">
<div className="container">
<h1>Hello, React!</h1>
</div>
</div>
);
}
});
This encourages more fine-grained detail in how we separate out components.
Makes it easy to find relevant details about a component. There's only one place to look!
Our Example

var HelloPage = React.createClass({
doSomething: function(){
alert("You got it, boss!");
},
render: function() {
return (
<div>
<div className="jumbotron">
<div className="container">
<h1>Hello, React!</h1>
</div>
</div>
<div className="container">
<div className="well">
<button
onClick={this.doSomething}>
Click Me!
</button>
<p className="pull-right">
Some interesting text goes here.
</p>
</div>
</div>
</div>
);
}
});
ReactDOM.render(
<HelloPage />,
document.getElementById("app")
);
Suddenly we need another button!

/* ... */
<div className="container">
<div className="well">
<button
onClick={this.doSomething}>
Click Me!
</button>
<p className="pull-right">
Some interesting text goes here.
</p>
</div>
</div>
<div className="container">
<div className="well">
<button
onClick={this.doSomething}>
Click Me!
</button>
<p className="pull-right">
Some interesting text goes here.
</p>
</div>
</div>
/* ... */

Composable Components

export default class FancyButton
extends React.Component {
render() {
const btn = this.props.btn;
return (
<div className="well">
<button onClick={
() => this.props.clickHandler(btn)
}>
Click Me!
</button>
<p className="pull-right">
Button { btn }
</p>
</div>
);
}
}
import FancyButton from './fancyButton.jsx';
/* ... */(
<div className="container">
<FancyButton btn="1" clickHandler={ this.doSomething }/>
<FancyButton btn="2" clickHandler={ this.doSomething }/>
</div>
/* ... */)
What are props?
let myData = this.props.data;
<MyComponent data="A value" />
"Props" are the properties you pass into a component. There are two main ways to do it.
<MyComponent data={ this.someData() } />
Constant values like HTML attributes
Dynamic values between { }
In your consumer
In your component
Props are available on this.props
Remember our pain points
-
Duplicating code
-
Writing "framework" code
-
Debugging unhelpful errors
We already saw how we can keep our code duplication to a minimum by extracting out components.
Let's have a look at the other two:
Writing JS with just a pinch of React
render: function() {
const data = [3,4];
return (
<div>
<div className="container">
{
data.map(function(btn, index){
return
<FancyButton key={index} btn={btn}/>;
})
}
</div>
</div>
);
}
React's small API surface area means more raw JavaScript and less React-specific code.

Here we're using a native JS array method to render multiple instances of a component.
The key prop is how React keeps track of the element for optimization. Every repeated element should have a unique key.
Useful error messages
Error: FancyButton is not defined(…)
Let's say we forget to import FancyButton. Some frameworks would fail silently but React?
Even without source maps and other luxuries, it's not hard to find the offending line.
React.createElement(
'div',
{ className: 'container' },
data.map(function (btn, index) {
return React.createElement(FancyButton, { // ...
})
)
React was designed to make web development faster and easier to do. Helpful errors contribute to this.
Redux is a predictable state container for JavaScript apps.

It was written by Dan Abramov for a conference talk called "Hot Reloading with Time Travel" in which he demonstrated time travel debugging.
Because state is deterministic, we can do really cool things, like rewind the application.
A pure function is one which, given the same input, will always produce the same output.
But first, pure functions
1 + 1 ->
function add(a, b){
return a + b;
}
2
Using pure functions to manage our state makes our application deterministic. If we do the same things with the same data, we'll get the same result, every time.
To reduce in a functional programming sense is to apply a function to a set of values, passing data forward each time.
Reducing
let a = [ 0, 1, 2, 3, 4, 5 ];
const reducer = (total, next) => { return total + next };
a.reduce(reducer) // or a.reduce(reducer, 0)
Notice that reducer is a pure function.
This will do 0 + 1, then 1 + 2, then 3 + 3, and so on.
To get started with Redux, you need a reducer function.
Reducers
A reducer function is a function which takes a state object, and an action, and returns a new state object.
function counter(state, action) {
if (typeof state === 'undefined') {
return 0
}
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
You must always return a state, even if you weren't given one. This is the initial state.
Actions have a type attribute so that you can update the state appropriately.
Now that we have a reducer function, we can create a store.
A store
That's all it takes. To start using the store, we dispatch an event.
var store = Redux.createStore(counter);
store.dispatch({ type: 'INCREMENT' });
The store will then pass the current state, and the action into the reducer and replace the current state with the new one.
Of course having a central location for all of our application's state wouldn't be useful if we didn't use the data we're putting in.
Consuming state updates
Or, if we want to always be notified when the state changes, we can subscribe.
var ourData = store.getState();
var handler = function(){ console.log( store.getState() ); };
store.subscribe(handler);
That's basically Redux in a nutshell.
Tying it together

In Redux, application state is stored in a nested object tree.
In React, data flows down the tree of components through props.
As you might expect, that means they work really well together.
Render subscription
Going back to our example, to add state to our application, we subscribe to the store and invoke render.
function render(){
ReactDOM.render(
<HelloPage state={ store.getState() } />,
document.getElementById("app")
)
}
store.subscribe(render);
Then we have access to our store throughout our app, so long as we pass it down the chain via props.
It's a one-way street
Our data flows downhill only. If a component wants to update the state, it needs to dispatch an action, which will propagate throughout the application.
return (
<button onClick={
() => store.dispatch({ type: 'INCREMENT' })
}> Increment </button>
);
When the event is dispatched, the store will pass the action to the reducer. When the new state is returned, the render method will be called.
React and Redux
These are both fantastic libraries, and each does its job exceptionally well.
And most importantly, they're fun to use.
They promote composition, and use of native JavaScript.
Thank you!
Workshop React+Redux
By Tarun Sharma
Workshop React+Redux
- 1,005