Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Getting into React

Getting into React

Intro presentation on React:

Have you ever wanted to try out React? It's a great library to help you build UIs for your single page apps. Together we'll walk through the basics of this great tool, looking at its component abstraction, how it helps you manage state, and how it will simplify your approach to UI development. We'll give you a feel for what a real React project is like, touching on all the pieces you'll need to try it out yourself. In the end, you'll have a better idea for what React is good for and how you can pick it up to help you on your next project.

Read more on React at jaketrent.com

#reactjs

Jake Trent

May 19, 2017
Tweet

More Decks by Jake Trent

Other Decks in Programming

Transcript

  1. REACT APPROACH VIEW ONLY ▸ Just a view ▸ Just

    a library ▸ Bring your own: app framework, client router, http library, module system, service layer, model library
  2. CUSTOM COMPONENTS: ▸ Semantic naming <SideNav> <Logo /> </SideNav> ▸

    Capitalized == custom ▸ Composable hierarchy
  3. REACT APPROACH SEPARATION OF CONCERNS ▸ Not technology ▸ Uses

    JSX (superset of JS) ▸ Include what looks like HTML in your functions function SideNav() { return <div>...</div> }
  4. COMPONENT STATE: PROPS ▸ Immutable bag of data ▸ Flow

    into component from parent function SideNav(props) { return <div>{props.links}</div> } ▸ Allow dynamic output ▸ Like arguments to a function
  5. JSX NOTE: CURLIES <div>{props.links}</div> ▸ Switch back to JS from

    HTML ▸ Inside curlies interpreted as {plain JS}
  6. TWO STYLES: COMPONENT SYNTAX ▸ Function style (aka “stateless components”)

    import React from ‘react’ class MyComponent extends React.Component {} ▸ Class style import React from ‘react’ function MyComponent() {}
  7. STATE INITIALIZATION: THIS.STATE import React from ‘react’ class Counter extends

    React.Component { constructor(props) { super(props) this.state = { count: 0 } } }
  8. STATE UPDATING: THIS.SETSTATE import React from ‘react’ class Counter extends

    React.Component { handleCountUpdate() { this.setState({ count: this.state.count + 1 }) } } ▸ (the mutating)
  9. COMPONENT CLASS: RENDERING import React from ‘react’ class SideNav extends

    React.Component { render() { return <div>{this.props.links}</div> } } ▸ Note `this.props.links` vs. `props.links` ▸ Must implement `render`
  10. COMPONENTS RENDER: VIRTUAL DOM import React from ‘react’ class SideNav

    extends React.Component { render() { return <div>{this.props.links}</div> } } ▸ Return DOM… Virtual DOM
  11. VIRTUAL DOM: ▸ In-memory representation ▸ Handled by React ▸

    Manages changes, dirty checking ▸ Auto updates the real DOM Real DOM Virtual DOM React-managed Browser-managed
  12. IN-MEMORY: DOM REPRESENTATION { '$$typeof': Symbol(react.element), type: 'div', key: null,

    ref: null, props: { '0': 'home', '1': 'about' }, _owner: null, _store: {} } ▸ Output of `React.createElement`
  13. REACT APPROACH NO TEMPLATE LANGUAGE ▸ JSX small differences vs.

    HTML: ▸ camelCase attributes - e.g., `onClick` (except aria-* & html-*) ▸ html* prefix - e.g., `htmlFor` ▸ alternate words - e.g., `className` ▸ Curlies revert back to {JS}
  14. CONNECT REACT TO: REAL DOM npm install react-dom import {

    render } from ‘react-dom’ render(<MyAppComponent />, document.getElementById(‘app’)) ▸ Call it once ▸ React handles translating VDOM to DOM
  15. REACT APPROACH LEARN ONCE, WRITE ANYWHERE ▸ Multiple render targets

    ▸ react-dom ▸ react-dom/server ▸ react-native
  16. INSERTED INTO DOM: “MOUNT” ▸ When your component is inserted

    into the real DOM ▸ 1. Created in memory ▸ 2. ReactDOM.render ▸ 3. Mount ▸ 4. Eventual removal called “unmount”
  17. in DOM / visible COMPONENT MOUNT: Mount Unmount constructor componentWillMount

    componentDidMount componentWillUnmount ▸ ▸ ▸ ▸ ▸ LIFECYCLE HOOKS time ▸
  18. ACCESS TO DOM: REF class UsernameField extends React.Component { render()

    { return <input ref={el => this.input = el} /> } }
  19. ACCESS TO DOM: DID MOUNT class UsernameField extends React.Component {

    componentDidMount() { this.input.focus() } render() { return <input ref={i => this.input = i} /> } }
  20. HANDLING: EVENTS <input onChange={this.handleChange} /> ▸ camelCase attributes ▸ eg,

    `onClick`, `onSubmit`, `onChange`, … handleChange(evt) { this.setState({ username: evt.target.value }) }
  21. EVENT GOTCHA: CALLBACK BINDING constructor(props) { super(props) this.handleChange = this.handleChange.bind(this)

    } handleChange(evt) { this.setState({ username: evt.target.value }) } ▸ bind to component context in constructor
  22. REAL: COMPONENT class UsernameField extends React.Component { constructor(props) { super(props)

    this.state = { username: ‘’ } this.handleChange = this.handleChange.bind(this) } componentDidMount() {…} handleChange() {…} render() {…} }
  23. REAL: COMPONENT class UsernameField extends React.Component { constructor() {…} componentDidMount()

    {…} handleChange() {…} render() { return <label htmlFor=“user”> {this.props.label} <input id=“user” ref={el => this.input = el} onChange={this.handleChange} /> </label> } }
  24. REAL: COMPONENT class UsernameField extends React.Component { constructor() {…} componentDidMount()

    {…} handleChange(evt) { this.setState({ username: evt.target.value }) } render() {…} }
  25. REAL: COMPONENT class UsernameField extends React.Component { constructor(props) { super(props)

    this.state = { username: ‘’ } this.handleChange = this.handleChange.bind(this) } componentDidMount() { this.input.focus() } handleChange(evt) { this.setState({ username: evt.target.value }) } render() { return <label htmlFor=“user”> {this.props.label} <input id=“user” ref={el => this.input = el} onChange={this.handleChange} /> </label> } }
  26. SHARING: DATA ▸ Lift to common parent ▸ Pass to

    children as `props` LoginForm UsernameField PasswordField
  27. SHARING: DATA LoginForm UsernameField PasswordField this.state = { username: ‘’

    password: ‘’ } <form> <UsernameField value={this.state.username} /> <PasswordField value={this.state.password} /> </form> <input value={props.value} /> <input value={props.value} /> ▸ Data flows down
  28. NOTIFYING: CHANGE ▸ Communicating change to parent ▸ Via callback

    functions LoginForm UsernameField PasswordField
  29. NOTIFYING: CHANGE LoginForm UsernameField PasswordField handleChange(evt) { this.setState({ [evt.target.name]: evt.target.value

    }) } <form> <UsernameField onChange={this.handleChange} value={this.state.username} /> <PasswordField onChange={this.handleChange} value={this.state.password} /> </form> <input name=“username” onChange={props.onChange} /> <input name=“password” onChange={props.onChange} /> ▸ Changes notify up
  30. REACT APPROACH EXPLICIT FLOW ▸ Strict conventions ▸ props ▸

    callbacks ▸ No automatic binding ▸ Explicit plumbing
  31. RENDERING: CHANGES ▸ Re-render triggered by changes to: ▸ this.props

    ▸ this.state ▸ Re-render self and children
  32. CALL RENDER: ONCE ▸ React takes care of all DOM

    updates ▸ No bit twiddling import { render } from ‘react-dom’ render(<LoginForm />, document.getElementById(‘app’))
  33. REACT APPROACH REPAINT EVERYTHING ▸ Declare UI based on state

    ▸ Pass to React as a whole to repaint everything ▸ Simple dev mental model
  34. REACT APPROACH REPAINT EVERYTHING ▸ Top-down render ▸ Frame by

    frame, like game programming ReactDOM.render(<TopComponent />)
  35. CONTROLLING: REPAINT ▸ State change causes repaint / update ▸

    Default behavior: `this.state` or `props` change ▸ Can change that behavior
  36. EXTRACTING: COMMONALITY const UsernameField = props => <label htmlFor=“user”> {props.label}

    <input id=“user” name=“username”
 onChange={props.onChange} /> </label> ▸ Start with similar, duplicated components: ▸ (and a similar PasswordField component)
  37. EXTRACTING: COMMONALITY const LoginField = props => <label htmlFor={props.name}> {props.label}

    <input id={props.name} name={props.name} onChange={props.onChange} type={props.type || ‘text’} /> </label> ▸ Create a common, generalized component:
  38. EXTRACTING: COMMONALITY const UsernameField = props => <LoginField label={props.label} name=“username”

    onChange={props.onChange} /> const PasswordField = props => <LoginField label={props.label} name=“password” onChange={props.onChange} type=“password” /> ▸ Wrapped in two specific components:
  39. DOCUMENTING: FOR THE FUTURE npm install prop-types ▸ Discoverability, learning,

    correct usage ▸ Good citizen ▸ Describing the public interface (props)
  40. DOCUMENTING: FOR THE FUTURE import PropTypes from ‘prop-types’ LoginField.propTypes =

    { label: PropTypes.string, name: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, type: PropTypes.string } ▸ List all props
  41. DOCUMENTING: FOR THE FUTURE <LoginField name=“username” /> ▸ At dev

    time, if misuse prop, get warning Warning: Failed prop type: The prop `onChange` is marked as required in `LoginField`, but its value is `undefined`.
  42. PROVIDING: DEFAULTS LoginField.defaultProps = { type: ‘text’ } ▸ When

    specific props aren’t sent ▸ Use these values
  43. PROJECT: SETUP import React, { Component } from 'react'; import

    logo from './logo.svg'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <div className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h2>Welcome to React</h2> </div> <p className="App-intro"> To get started, edit <code>src/App.js</code> and save to reload. </p> </div> ); } } export default App;
  44. PROJECT: BUILD ▸ Webpack-based ▸ Everything’s a module ▸ Webpack

    is powerful ▸ Complicated, and worth learning import './App.css'
  45. COMPONENT: STYLING ▸ Many options ▸ Influenced by React community

    portable, isolated, rebel external, cascade, traditional Inline Stylesheet
  46. REACT APPROACH RETHINK BEST PRACTICES ▸ eg, inline styles ▸

    or repaint “everything” on update?!
  47. CSS MODULES: ISOLATED ▸ CSS exposed in export object ▸

    Use original selector in code import css from ‘./index.css’ <div className={css.mySelector} />
  48. CSS MODULES: ISOLATED ▸ Value of selector name in export

    object is hashed <div class=“mySelector__4ef12” /> ▸ Making them unique in global namespace ▸ Changes isolated to component my-component.js my-component.css <div className={css.mySelector} />
  49. CSS MODULES: EXPLICIT DEPENDENCIES @import “./common.css”; .mySelector { composes: commonSelector;

    color: red; } class=“mySelector__4ef12 commonSelector__ab5tc”
  50. COMPONENT: TESTING npm install jest --save-dev test(‘basic assertion’, () =>

    { expect(true).toEqual(true) }) ▸ Built on Jasmine ▸ Helpful with mocking ▸ Snapshot testing
  51. SNAPSHOT: TESTING test(‘render correctly’, () => { const tree =

    renderer.create(<MyComponent />) expect(tree).toMatchSnapshot() }) ▸ Similar to taking a screenshot ▸ Comparing changes against original screenshot ▸ But “screenshot” is just a text serialization
  52. CLIENT-SIDE: ROUTER ▸ Many options: ▸ react-router ▸ page.js <Router>

    <Route path=“/login” component={LoginPage} /> </Router> npm install react-router-dom
  53. PROJECT: LAYOUT ▸ Instead of by tiers "## controllers "##

    db "## models "## services $## view "## alerts "## game "## home $## login ▸ By features
  54. PROJECT: LAYOUT ▸ Tests next to src login "## __specs__

    % "## index.spec.js % $## validators.spec.js "## index.css "## index.js "## sub-component.css "## sub-component.js $## validators.js
  55. STATE MANAGEMENT: ▸ Based on Flux pattern ▸ A pattern

    to help you organize app state ▸ Will complicate your app ▸ If benefit > complexity, do it ▸ Use `props` and `this.state` otherwise REDUX
  56. REACT IN THE: LARGE ▸ Still the best experience I’ve

    had ▸ Abstractions scale well ▸ Redux implements a solid pattern at scale
  57. INTRODUCE REACT: GRADUALLY <div> My Other-Framework app <div id=“small-piece”></div> </div>

    ReactDOM.render(<LoginForm />, document.getElementById(‘small-piece’)) ▸ Just need a DOM element to own
  58. COMPONENTS ARE FOR: SHARING ▸ Great encapsulation ▸ Simple public

    API ▸ Built-in documentation ▸ Productive community npm publish
  59. FIND SUPPORT: IN THE COMMUNITY ▸ Questions: ▸ StackOverflow #reactjs

    ▸ Forum: discuss.reactjs.org ▸ Chat: “reactiflux” discord, #reactjs IRC ▸ OSS: github.com/reactjs ▸ Docs: facebook.github.io/react
  60. A COUPLE: EXAMPLE PROJECTS github.com/jaketrent/wordspies ▸ React + Redux +

    more: github.com/jaketrent/mastermind-saga ▸ Just React: ▸ (Disregard server portions)
  61. USE: WHAT YOU KNOW ▸ You know: ▸ How components

    work ▸ The React approach ▸ How to start a project ▸