React 101

 

React is...

  • Not a framework
  • a Library for creating User Interfaces
  • the V in MVC
  • Data-Driven
  • Declarative

Why React?

Why React?

 

Speed

 

Why React?

 

Virtual DOM

Why React?

 

Reusable code

Components, Components, Components

Why React?

 

React Components

Why React?

import React from 'react';
import Menu from './Menu';
import SideMenu from './SideMenu';
import SideMenuItem from './SideMenu/SideMenuItem'

export default const App = () => {
    
    return (   
        <SideMenu>
            <SideMenuItem title="Item 1" icon="fa fa-home">
                <p>Content for side menu item 1</p>
            </SideMenuItem>
        </SideMenu>
        <Main>
        </Main>
    );
};

 

React Components

Why React?

 

Browser Optional

Server-side rendering, React Native

Why React?

app.get('/', function(req, res){
  res.render('index', {
    react: ReactDOM.renderToString(HelloMessage({name: "John"}))
  })
})

 

Server-side render

Why React?

 

React Native

JSX

JSX

DOM-like Syntactical sugar

JSX

const el = (
    <div>
        <p>Hi!</p>
        <MyComponent/>
    </div>
)
const el = React.DOM.div(null, 
        React.DOM.p(null, "Hi!"),
        MyComponent(null)
);

DOM-like Syntactical sugar

JSX

class is now className

const el = (
    <div className="heading">
        <p>Hi!</p>
        <MyComponent/>
    </div>
)
const el = (
    <div class="heading">
        <p>Hi!</p>
        <MyComponent/>
    </div>
)

JSX

function getGreeting(user) {
    if (user) {
        return <h1>Hello, {formatName(user)}!</h1>;
    }
        return <h1>Hello, Stranger.</h1>;
}

Expressions go into {}, with access to current JavaScript scope:

JSX

Conditional Rendering

const loading = true;

const renderLoadingScreen = () => {
    if (loading) {
        return <LoadingComponent/>
    } else {
        return <p>Hi!</p>;
    }
};

const el = (
    <div>
        { renderLoadingScreen() }
    </div>
)

JSX

const loading = true;

const el = (
    <div>
        { loading ? <LoadingComponent/> : '<p>Hi!</p>' }
    </div>
)
const loading = true;

const renderLoadingScreen = () => {
    if (loading) {
        return <LoadingComponent/>
    } else {
        return <p>Hi!</p>;
    }
};

const el = (
    <div>
        { renderLoadingScreen() }
    </div>
)

Conditional Rendering

Ternary short-hand:

JSX

const skills = ['javascript', 'photoshop'];

const renderChildren = () => {
    return skills.map(skill => <span>{skill}</span>);
};

const el = (
    <div>
        <p>Skills: { renderSkills() }</p>
    </div>
)

Rendering data sets is done using .map()

React Components

React Components

React Components

Data flows down

Events bubble up

React Components

 

Stateless Components

React Components

 

Stateless component return a function

import React from 'react';
import CountDownTimer from './CountDownTimer';

export const App = () => {

    return (
            <div className="app">
                <CountDownTimer></CountDownTimer>
            </div>
    )
            
};

React Components

import React from 'react';

const CountDownTimer = () => {
    return <h1>05:00</h1>
};

export default CountDownTimer;
import React from 'react';
import CountDownTimer from './CountDownTimer';

export const App = () => {

    return (
            <div className="app">
                <CountDownTimer></CountDownTimer>
            </div>
    )
            
};

 

Stateless component return a function

React Components

 

Result:

React Components

 

Passing Data

React Components

 

Data is passed via "props":

import React from 'react';
import CountDownTimer from './CountDownTimer';

export const App = () => {

    return (
            <div className="app">
                <CountDownTimer startTime="5"></CountDownTimer>
            </div>
    )
            
};

React Components

import React from 'react';
import CountDownTimer from './CountDownTimer';

export const App = () => {

    return (
            <div className="app">
                <CountDownTimer startTime="5"></CountDownTimer>
            </div>
    )
            
};
import React from 'react';

const CountDownTimer = (props) => {
    return <h1>{props.startTime}</h1>
};

export default CountDownTimer;

 

Data is passed via "props":

 

props are accessible inside the component:

React Components

Result:

import React from 'react';
import moment from 'moment';

export const CountDownTimer = (props) => {

    const startTime = moment(props.startTime, 'mm').format('MM:SS');
    return <h1>{startTime}</h1>

};

 

Using NPM libs to manipulate props:

npm install --save moment

React Components

import React from 'react';
import moment from 'moment';

export const CountDownTimer = (props) => {

    const startTime = moment(props.startTime, 'mm').format('MM:SS');
    return <h1>{startTime}</h1>

};
npm install --save moment

React Components

 

Using NPM libs

React Components

 

Prop Types

React Components

<User 
    name="Anzor"
    id={10} 
    employed={true}
    skills={['javascript', 'photoshop', '3d']}
    employer={{ name: 'BuildDirect' }}
    photo={<UserPhoto id={10}></UserPhoto>}>
</User>

Prop types include String, Number, Boolean, Object, Array, other React Components

React Components

const User = (props) => {

    const renderSkills = () => {
        return props.skills.map(skill => <p>{skill}</p>);
    };

    return (
        <div className="user">
            <div>{props.photo}</div>
            <p>{props.name}</p>
            <p>{props.id}</p>
            <p>{props.employer.name</p>
            {renderSkills()}
        </div>

    )   
}

Handling props

React Components

... 
}

User.propTypes = {
    id: React.PropTypes.number.isRequired,
    employer: React.PropTypes.object.isRequired,
    name: React.PropTypes.string.isRequired,
    skills: React.PropTypes.array,
    employed: React.PropTypes.bool.isRequired,
    photo: React.PropTypes.element.isRequired
}

export default User;

 

Typechecking with Props

React Components

... 
}

User.propTypes = {
    id: React.PropTypes.number.isRequired,
    employer: React.PropTypes.object.isRequired,
    name: React.PropTypes.string.isRequired,
    skills: React.PropTypes.array,
    employed: React.PropTypes.bool.isRequired,
    photo: React.PropTypes.element.isRequired
}

export default User;

 

Typechecking with Props

React Components

 

Maintaining State

 

Stateful component is a class

import React, { Component } from 'react';
import moment from 'moment';

export class CountDownTimer extends Component {

    constructor(props) {
        super(props);
        // initialize state to what's passed in
        this.state = {
            time: moment(props.startTime, 'mm')
        };
    }

    render() {
        // render value stored in state
        const startTime = this.state.time.format('mm:ss');
        return <h1>{startTime}</h1>
    }

};

React Components

 

this.setState() triggers a re-render of virtual DOM

import React, { Component } from 'react';
import moment from 'moment';

export class CountDownTimer extends Component {

    constructor(props) {
        super(props);
        this.state = {
            time: moment(props.startTime, 'mm')
        };
        setInterval(() => {
            const time = this.state.time.subtract({ seconds: 1 });
            this.setState({ time });
        }, 1000);
    }

    render() {
        const startTime = this.state.time.format('mm:ss');
        return <h1>{startTime}</h1>
    }

};

React Components

 

Adding Timer logic using setState()

React Components

 

Events

React Components

React Components

...
    start() {...}

    render() {
        return (
                <div className="app">
                    <CountDownTimer startTime="5"></CountDownTimer>
                    <button onClick={this.start}>Start Timer</button>
                </div>
        )
    }
...

DOM events: onClick, onChange, etc...

React Components

import React, {Component} from 'react';
import CountDownTimer from './CountDownTimer';

export class App extends Component {

    countDownTimerComplete() {
        alert('time\'s up!');
    }

    render() {
        return (
                <div className="app">
                    <CountDownTimer 
                        startTime="5" 
                        onTimerDone={this.countDownTimerComplete}>
                    </CountDownTimer>
                </div>
        )
    }
            
};

Custom events:

React Components

Emitting custom events:


class CountDownTimer extends Component {

    constructor(props) {
        super(props);
        this.state = {};
    }
...
    decrement() {
        if (time === 0) {
            // emit event by executing the function
            this.props.onTimerDone();
            ...
        }
    }
...

React Components

Typechecking function props:


class CountDownTimer extends Component {...}

CountDownTimer.propTypes = {
    onTimerDone: React.PropTypes.func.isRequired
}

export default CountDownTimer;

React Components

 

Component Children

aka "transclude"

React Components

import TabHeader from './TabHeader';

const UI = () => {
...
    <Tabs>
        <TabHeader>Tab 1 Content</TabHeader>
    ...
    <Tabs>
};
const TabHeader = (props) => {
    <div className="tab-header">{props.children}</div>
}

React Components

<div className="tab-header">Tab 1 Content</div>
const TabHeader = (props) => {
    <div className="tab-header">{props.children}</div>
}
import TabHeader from './TabHeader';

const UI = () => {
...
    <Tabs>
        <TabHeader>Tab 1 Content</TabHeader>
    ...
    <Tabs>
};

React Components

 

Component LifeCycle

React Components

Demo

React 101

By Anzor B

React 101

  • 1,014