React In Practice

JSX Spread Attributes

Mutating Props is Bad

Spread Attributes

var component = <Component />;
  component.props.foo = x; // bad
  component.props.bar = y; // also bad
 var props = { foo: 'default' };
  var component = <Component {...props} foo={'override'} />;
  console.log(component.props.foo); // 'override'

Prop Validation

 

Note that for performance reasons,  propTypes is only checked in development mode.

Transferring Props: A Shortcut

var CheckLink = React.createClass({
  render: function() {
    // This takes any props passed to CheckLink and copies them to <a>
    return <a {...this.props}>{'√ '}{this.props.children}</a>;
  }
});

 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number).isRequired,

 optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),

ES6 Classes

export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
}


Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };

do not support mixins

Transferring with ... in JSX

function FancyCheckbox(props) {
  var { checked, ...other } = props;
  var fancyClass = checked ? 'FancyChecked' : 'FancyUnchecked';
  // `other` contains { onClick: console.log } but not the checked property
  return (
    <div {...other} className={fancyClass} />
  );
}

ReactDOM.render(
  <FancyCheckbox checked={true} onClick={console.log.bind(console)}>
    Hello world!
  </FancyCheckbox>,
  document.getElementById('example')
);

  DOM difference

Built-in DOM nodes use className and htmlFor 

Custom elements use class and for 

<div className="foo" />
<my-tag class="foo" />

Ref Callback

render: function() {
    return (
      <TextInput
        ref={function(input) {
          if (input != null) {
            input.focus();
          }
        }} />
    );
  },

The referenced component will be passed in as a parameter

Immutability Helpers

var newData = deepCopy(myData);
newData.x.y.z = 7;
newData.a.b.push(9);

The problem

syntactic sugar

var update = require('react-addons-update');

var newData = update(myData, {
  x: {y: {z: {$set: 7}}},
  a: {b: {$push: [9]}}
});

Context

var Button = React.createClass({
  contextTypes: {
    color: React.PropTypes.string
  },
  render: function() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
});

var Message = React.createClass({
childContextTypes: {
    color: React.PropTypes.string
  },
  getChildContext: function() {
    return {color: "purple"};
  },
  render: function() {
    return (
      <div>
        <Button>Delete</Button>
      </div>
    );
  }
});

Context

best use cases

passing down the logged-in user, the current language, or theme information.

 

Other true globals

 

PureRenderMixin


import PureRenderMixin from 'react-addons-pure-render-mixin';
class FooComponent extends React.Component {
  constructor(props) {
    super(props);
    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
  }

  render() {
    return <div className={this.props.className}>foo</div>;
  }
}

 it compares the current props and state with the next ones and returns false if the equalities pass.

Shallow Compare


var shallowCompare = require('react-addons-shallow-compare');
export class SampleComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState);
  }

  render() {
    return <div className={this.props.className}>foo</div>;
  }
}

ShallowCompare is a helper function to achieve the same functionality as PureRenderMixinwhile using ES6 classes with React

Keyed Fragments


var Swapper = React.createClass({
  propTypes: {
    // `leftChildren` and `rightChildren` can be a string, element, array, etc.
    leftChildren: React.PropTypes.node,
    rightChildren: React.PropTypes.node,

    swapped: React.PropTypes.bool
  },
  render: function() {
    var children;
    if (this.props.swapped) {
      children = [this.props.rightChildren, this.props.leftChildren];
    } else {
      children = [this.props.leftChildren, this.props.rightChildren];
    }
    return <div>{children}</div>;
  }
});

The problem

Keyed Fragments


var createFragment = require('react-addons-create-fragment');

if (this.props.swapped) {
  children = createFragment({
    right: this.props.rightChildren,
    left: this.props.leftChildren
  });
} else {
  children = createFragment({
    left: this.props.leftChildren,
    right: this.props.rightChildren
  });
}

Solution

Performance Tools


require('react-addons-perf')

Perf.start()

Perf.stop()

Perf.getLastMeasurements()

Perf.printInclusive(measurements)

Perf gives overview of your app's overall performance

Advanced Performance

  • shouldComponentUpdate
  • Immutable
var component = <Component />;
  component.props.foo = x; // bad
  component.props.bar = y; // also bad
 var props = { foo: 'default' };
  var component = <Component {...props} foo={'override'} />;
  console.log(component.props.foo); // 'override'

react-in-practice

By jingliu

react-in-practice

  • 417