We take developers from good to great

WE ARE THE JSLEAGUE

One app, 3 Frameworks
30th of May

bit.ly/voxxed-react


React
Module 1
Fundamentals

Module 1
But first, a few considerations...

Module 1
Templating and state management



Module 1
Templating and state management

Cannot stress this enough.
Everything is JS

Module 1
First stop: Components
Two types of components:
- "Class Components"
- "Functional Components"

Module 1

Module 1
Dumb Component
import React from 'react';
export default ({ counter, setCounter }) => (
<div>
<span>Count: {counter}</span>
<button onClick={() => setCounter(counter + 1)}>+1</button>
</div>
);

Module 1
Dumb Component
export default function() {
var _component = function() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _this;
}
Object(babel_runtime_helpers.createClass(_component, [{
key: "render",
value: function render() {
var counter = this.props.counter;
var setCounter = this.props.setCounter;
return React.createElement(React.div, {
children: React.createElement(...),
});
}
}]);
return _component;
}

Module 1
Stateful Component
import React, { Component } from 'react';
import CounterComponent from './counter';
export default class MyComponent extends Component {
state = { counter: 0 }
updateCounter = value => this.setState({ counter: value });
render() {
const { counter } = this.state;
return (
<CounterComponent
counter={counter}
setCounter={this.updateCounter}
/>
);
}
}

Module 1
Stateful Component (don't)
import React, { Component } from 'react';
import CounterComponent from './counter';
export default class MyComponent extends Component {
constructor() {
super();
this.state = { counter: 0 };
this.updateCounter = this.updateCounter.bind(this);
}
updateCounter(value) { this.setState({ counter: value }); }
render() {
const { counter } = this.state;
return (
<CounterComponent
counter={counter}
setCounter={this.updateCounter}
/>
);
}
}

Module 1
State?
class MyComponent extends Component {
...
render() {
const { isEditing } = this.state;
const { data, updateData } = this.props;
...
}
}
class RootComponent extends Component {
...
render() {
return <MyComponent data={...} updateData={...} />
}
}

Module 1
Lifecycle
class MyComponent extends Component {
// on initial render
componentWillMount() //deprecated
componentDidMount()
// props changes
componentWillReceiveProps()
componentShouldUpdate()
componentWillUpdate()
// state changes
componentWillUpdate()
// component is no longer being rendered
componentWillUnmount()
...
}

Module 1
React Hooks
export default (props) => {
const [counter, setCounter] = useState(0);
useEffect(
() => document.head.title = "Ready to count",
[],
);
useEffect(
() => document.head.title = `Counted ${counter} times`,
[counter],
);
return (
<div>
<h2>Counter App</h2>
<div>Counted {counter} times!</div>
<button onClick={() => setCounter(counter + 1)}>Add one</button>
<button onClick={() => setCounter(counter + 5)}>Add five</button>
<button onClick={() => setCounter(counter - 1)}>Subtract one</button>
</div>
);
}


React
Module 2
State / Data

Module 2
Two types of Data
- Properties (props)
- Component State (state)

Module 2
Class Component
import React, { Component } from 'react';
import CounterComponent from './counter';
export default class MyComponent extends Component {
state = { counter: 0 }
updateCounter = value => this.setState({ counter: value });
render() {
const { counter } = this.state;
const { firstName, lastName } = this.props;
return (
<CounterComponent
counter={counter}
name={`${firstName} ${lastName}`}
setCounter={this.updateCounter}
/>
);
}
}

Module 2
React Hooks
export default ({ name }) => {
const [counter, setCounter] = useState(0);
useEffect(
() => document.head.title = "Ready to count",
[],
);
useEffect(
() => document.head.title = `Counted ${counter} times`,
[counter],
);
return (
<div>
<h2>Counter App</h2>
<h1>Hi, my name is {name}</h1>
<div>Counted {counter} times!</div>
<button onClick={() => setCounter(counter + 1)}>Add one</button>
<button onClick={() => setCounter(counter + 5)}>Add five</button>
<button onClick={() => setCounter(counter - 1)}>Subtract one</button>
</div>
);
}


React
Module 3
Global State

Module 3

Redux

Module 3
Mobx

Why?
Redux Example: bit.ly/voxxed-redux
Mobx Example: bit.ly/voxxed-mobx

Module 3


React
Module 4
HTTP / Routing
HTTP?
Anything you like.

Module 4
Routing
Conditional.
Not Structural

Module 4
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
export default ({ isAdmin }) => (
<Router>
<Switch>
<Route exact path="/" component={HomeComponent} />
<Route path="/users" component={UsersLayout} />
</Switch>
<footer>
<Route
exact
path="/admin"
render={() => <Link to="/">Home</Link>}
/>
{isAdmin &&
<Route
path="/not-an-admin"
render={() => <Link to="/admin">Admin</Link>}
/>
}
</footer>
</Router>
);

Module 4

React
Module 5
Extras
Suspense
Lazy loading
+ Code Splitting
+ Fallback rendering
+ Error Boundary Handling

Module 5
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
);

Module 5
Thank you!

One App, 3 Frameworks -- React
By Sabin Marcu
One App, 3 Frameworks -- React
- 496