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: 

  1. "Class Components"
  2. "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

 

  1. Properties             (props)
  2. 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

  • 469