React

Let virtual DOM do its magic.

Topics: tools, development

Author: Maitrik

Articles

What is React ?

Basic

  • It is JS library not framework.

  • Declarative

  • MVC - Only View

  • Three main reasons

    • Components | functions, reusable, manage private states
    • Reactive updates | reach will react , take updates to brwosers
    • Virtual views in memory | html in JS
  • Two type of Components

    • Function Components - Use JSX
    • Class Components - Virtual
  • Use require and module.exports to access one file from another

  • A React app is basically just a lot of components, setting state and passing props to one another.

Tradeoffs

OtherReact
FrameworkLibrary
ConciseExplicit
Twoway BindingOne Way Binding
Template-centricJS-Centic
JS in HtmlHtml in JS
Separate (MVC)Single File (HTML/CSS/JS)
Standard ComponentNon-Standard
CommunityCorporate ( FB )
WebComponentReact
TemplatesJSX
Custom ElemenDeclare React Components
Shadow DOMCSS Modules, CSS in JS
ImportsOne component per file

PropTypes vs Typescript(MS) vs Flow(FB)

  • PropTypes run on Runtime
  • Typescript check at Compile time
  • Flow can be run either runtime or compile time

JSX

  • JSX is a syntax extension for JavaScript. It was written to be used with React. JSX code looks a lot like HTML.

  • There's a rule that we haven't mentioned: a JSX expression must have exactly one outermost element.

  • class become className

  • you have to include the slash in end of tag. If you write a self-closing tag in JSX and forget the slash, you will raise an error.

  • Wrapping your code in curly braces between JSX tags, treat it like ordinary JavaScript and not like JSX.

    var theBestString = 'tralalalala i am da best';
    var judgmental = Math.random() < 0.5;
    var math = (
        <h1>
        2 + 3 = {2 + 3}
        </h1>
    );
    var JSKIf = (
        <h1>
            { if (purchase.complete) 'Thank you for placing an order!' }
        </h1>
    );
    function myfunction (e) {
    
    ReactDOM.render(
        <h1>{2 + 3}</h1>,
        <h1 className="big">{2 + 3}</h1>,
        <h1>{theBestString}</h1>,
        <h1 onClick={myfunction} >Click Here</h1>,
        { !judgmental && <h1>Nacho Cheez Straight Out The Jar</h1> }
        math,
        document.getElementById('app')
    );
    

React Component

  • React.Component is an abstract base class, so it rarely makes sense to refer to React.Component directly.

  • Instead, you will typically subclass it, and define at least a render() method.

    var React = require('react');
    var ReactDOM = require('react-dom');
    
    var Button = React.createClass({
    scream: function () {
        alert('AAAAAAAAHHH!!!!!');
    },
    name : "Ths is button",
    
    render: function () {
        return <button onClick={this.scream}>{this.name}</button>;
    }
    });
    
    ReactDOM.render (
    <Button />,
    document.getElementById('app')
    );
    

Props

  • Every component has something called props
  • A component's props is an object. It holds information about that component.
  • To see a component's props object, you use the expression this.props
  • props (short for properties) are a Component's configuration, its options if you may. They are received from above and immutable as far as the Component receiving them is concerned.
  • A Component cannot change its props, but it is responsible for putting together the props of its child Components.

State

  • The state starts with a default value when a Component mounts and then suffers from mutations in time (mostly generated from user events). It's a serializable* representation of one point in time--a snapshot.

  • React components will often need dynamic information in order to render.

  • There are two ways for a component to get dynamic information: props and state. Besides props and state, everything in a component should always stay exactly the same.

  • Unlike props, a component's state is not passed in from the outside. A component decides its own state

  • you can't call "this.setState" from inside of the "render" function! "this.setState" automatically calls "render". If "render" calls "this.setState", you will create an infinite loop.

    var React = require('react');
    var ReactDOM = require('react-dom');
    
    var green = '#39D1B4';
    var yellow = '#FFD712';
    
    var Toggle = React.createClass({
    getInitialState: function () {
        return { color: green };
    },
    
    changeColor: function () {
        var color = this.state.color == green ? yellow : green;
        this.setState({ color: color });
    },
    
    render: function () {
        return (
        <div style={{background: this.state.color}}>
            <h1>
            Change my color
            </h1>
            <button onClick={this.changeColor}>
            Change color
            </button>
        </div>
        );
    }
    });
    
    ReactDOM.render(
    <Toggle />,
    document.getElementById('app')
    );
    

Prop vs State

  • props and state both hold information relating to the component, they are used differently and should be kept separate.
  • "props" is short for "properties" so nothing particularly fancy there.
  • props should not change
  • props contains information set by the parent component (although defaults can be set) and should not be changed.
  • props are a way of passing data from parent to child. ...
  • state contains "private" information for the component to initialise, change, and use on it's own.
  • State is reserved only for interactivity, that is, data that changes over time.

Stateless Components Inherit From Stateful Components

Pattern 1 :
  • A stateful component passes its state down to a stateless component.
  • Stateful Parent passes a prop to stateless Child.
  • A stateful component class stores information as state.
  • A stateless component class displays that state.
  • A different stateless component class displays a way to change that state.
Pattern 2 :
  • The stateless, child component will update the state of the parent component.
  • A stateful, parent component passes down an event handler to a stateless, child component.
  • The child component then uses that event handler to update its parent's state.
Pattern 3 :
  • You will have one stateless component display information, and a differenstateless component offer the ability to change that information.

  • An instance of the stateful component class is rendered.

  • One stateless child component displays the state, and a different stateless child component displays a way to change the stateful component

  • Files

  • Stateful / Parent.js

    var React = require('react');
    var ReactDOM = require('react-dom');
    var Child = require('./Child');
    var Sibling = require('./Sibling');
    
    var Parent = React.createClass({
      getInitialState: function () {
        return { name: 'Frarthur' };
      },
    
      changeName: function (newName) {
        this.setState({
          name: newName
        });
      },
    
      render: function () {
        return (
          <div>
            <Child onChange={this.changeName} />
            <Sibling name={this.state.name} />
          </div>
        );
      }
    });
    
    ReactDOM.render(
      <Parent />,
      document.getElementById('app')
    );
    
  • Stateless / Child.js

    var React = require('react');
    
    var Child = React.createClass({
      handleChange: function (e) {
        var name = e.target.value;
        this.props.onChange(name);
      },
    
      render: function () {
        return (
          <div>
            <select
              id="great-names"
              onChange={this.handleChange}>
    
              <option value="Frarthur">Frarthur</option>
              <option value="Gromulus">Gromulus</option>
              <option value="Thinkpiece">Thinkpiece</option>
            </select>
          </div>
        );
      }
    });
    
    module.exports = Child;
    
  • Stateless / Sibling.js

    var React = require('react');
    
    var Sibling = React.createClass({
      render: function () {
        var name = this.props.name;
        return (
          <div>
            <h1>Hey, my name is {name}!</h1>
            <h2>Don't you think {name} is the prettiest name ever?</h2>
            <h2>Sure am glad that my parents picked {name}!</h2>
          </div>
        );
      }
    });
    
    module.exports = Sibling;
    
Pattern 4 :
  • Inline Styles, dividing components into presentational components and containecomponents.

  • <h1 style={{ color: 'red' }}>Hello world</h1>

  • The outer curly braces inject JavaScript into JSX. They say, "everything between us should be read as JavaScript, not JSX."

  • The inner curly braces create a JavaScript object literal. They make this a valid JavaScript object

  • Nicer approach is to store a style object in a variable, and then inject that variable into JSX.

  • Normally Style names are written in hyphenated-lowercase but in React, those same names are instead written in camelCase. backgroundColor: "green"

  • A style value as a number, then the unit "px" is assumed. fontSize: 50

  • Style file / style.js

    var blue  = 'rgb(139, 157, 195)';
    var darkBlue  = 'rgb(059, 089, 152)';
    var lightBlue = 'rgb(223, 227, 238)';
    var grey      = 'rgb(247, 247, 247)';
    var white     = 'rgb(255, 255, 255)';
    var fontSize   = '4em';
    
    module.exports = {
      blue: blue,
      darkBlue: darkBlue,
      lightBlue: lightBlue,
      grey: grey,
      white: white,
      fontSize:   fontSize
    };
    
  • Stateless / Sibling.js

    var React = require('react');
    var ReactDOM = require('react-dom');
    var styles = require('./facebookStyles');
    
    var divStyle = {
      backgroundColor: styles.darkBlue,
      color:           styles.white,
      fontSize:           styles.fontSize
    };
    
    var Wow = React.createClass({
      render: function () {
        return (
          <div style={divStyle}>
            Wow, I stole these colors from Facebook!
          </div>
        );
      }
    });
    
    ReactDOM.render(
      <Wow />,
      document.getElementById('app')
    );
    
Pattern 5 :
  • Separating presentational components from display components.
  • Separating container components from presentational components is a popular React programming pattern.
  • If a component has to have state, make calculations based on props, or manage any other complex logic, then that component shouldn't also have to render HTML-like JSX.
  • Following this pattern separates your business logic from your presentational logic.
  • HTML code in presentational component component file and Export by exports in end.
  • Business logic in container file and import component by require on top.
  • When you separate a container component from a presentational component, the presentational component will always end up with one render function, and no other properties.
  • A container does data fetching and then renders its corresponding sub-component. That’s it.
  • Stateless functional components

    • If you have a component class with nothing but a render function, then you can rewrite that component class in a very different way.

    • Instead of using React.createClass, you can write it as JavaScript function!

      // Normal way to display a prop:
      var MyComponentClass = React.createClass({
        render: function () {
          return <h1>{this.props.title}</h1>;
        }
      });
      
      // Stateless functional component way to display a prop:
      function MyComponentClass (props) {
        return <h1>{props.title}</h1>;
      }
      

propTypes

  • propTypes are useful for two reasons

    • Prop validation : Validation can ensure that your props are doing what they're supposed to be doing. If props are missing, or if they're present but they aren't what you're expecting, then a warning will print in the console.

    • Documentation : Documenting props makes it easier to glance at a file and quickly understand the component class inside. When you have a lot of files, and you will, this can be a huge benefit.

      var React = require('react');
      
      var MessageDisplayer = React.createClass({
        // This propTypes object should have
        // one property for each expected prop:
        propTypes: {
          message: React.PropTypes.string
        },
      
        render: function () {
          return <h1>{this.props.message}</h1>;
        }
      });
      

Forms

  • A traditional form doesn't update the server until a user hits "submit."

  • Controlled component : An uncontrolled component is a component that maintains its own internal state.

  • Uncontrolled component : A controlled component is a component that does not maintain any internal state.

    var React = require('react');
    var ReactDOM = require('react-dom');
    
    var Input = React.createClass({
    
      getInitialState: function () {
        return {
          userInput: ''
        };
      },
    
      handleUserInput: function (e) {
        this.setState({
          userInput: e.target.value
        });
      },
    
      render: function () {
        return (
          <div>
            <input
              type="text"
              onChange={this.handleUserInput}
              value={this.state.userInput}
            />
            <h1>{this.state.userInput}</h1>
          </div>
        );
      }
    });
    
    ReactDOM.render(
      <Input />,
      document.getElementById('app')
    );
    

Lifestyle methods

  • Lifecycle methods are methods that get called at certain moments in a component's life.
  • Lifecycle method can get called at :
    • Right before a component renders for the first time.
    • Right after a component renders, every time except for the first time.
    • At different moments in a component's life.
Mounting lifecycle methods
  • When a component mounts, Mounting lifecycle method automatically calls these three methods :

    1. ComponentWillMount
    2. Render
    3. ComponentDidMount
  • If you need to do something only the first time that a component renders, then it's probably a job for a mounting lifecycle method!

    var React = require('react');
    var ReactDOM = require('react-dom');
    
    var Flashy = React.createClass({
      componentWillMount: function () {
        alert('AND NOW, FOR THE FIRST TIME EVER...  FLASHY!!!!');
      },
    
      componentDidMount: function () {
        alert('YOU JUST WITNESSED THE DEBUT OF...  FLASHY!!!!!!!');
      },
    
      render: function () {
    
        alert('Flashy is rendering!');
        return (
          <h1 style={{ color: this.props.color }}>
            OOH LA LA LOOK AT ME I AM THE FLASHIEST
          </h1>
        );
      }
    
    });
    
    ReactDOM.render(
      <Flashy color='red' />,
      document.getElementById('app')
    );
    
    setTimeout(function () {
      ReactDOM.render(
        <Flashy color='green' />,
        document.getElementById('app')
      );
    }, 2000);
    
Updating lifecycle methods
  • The first time that a component instance renders, it does not update.
  • A component updates every time that it renders, starting with the second render.
  • There are five updating lifecycle methods:
    1. componentWillReceiveProps
    2. shouldComponentUpdate
    3. componentWillUpdate
    4. render
    5. componentDidUpdate
Unmounting lifecycle methods
  • componentWillUnmount gets called right before a component is removed from the DOM.

    var React = require('react');
    
    var Enthused = React.createClass({
      interval: null,
    
      componentDidMount: function () {
        this.interval = setInterval(function(){
          this.props.addText('!');
        }.bind(this), 15);
      },
      componentWillUnmount: function (prevProps, prevState) {
        clearInterval(this.interval);
      },
      render: function () {
        return (
          <button onClick={this.props.toggle}>
            Stop!
          </button>
        );
      }
    });
    
    module.exports = Enthused;