Slide 1

Slide 1 text

With react-controllables Controllable React Components

Slide 2

Slide 2 text

HZDG.COM LETTERTWO ERIC ELDREDGE LETTERTWO@GMAIL.COM HZDG PHOTO MISSING

Slide 3

Slide 3 text

The Tao of the React Component Props vs State

Slide 4

Slide 4 text

When do you use props vs. state?

Slide 5

Slide 5 text

Always use props… • Enables composition • Keeps your React Components pure

Slide 6

Slide 6 text

…unless you need state • Some components are affected by user interactions • Since props are immutable, interactions that change the component must either be handled by the parent component, or translated to state

Slide 7

Slide 7 text

React Form Components Controlled: Uncontrolled: Uncontrolled (with a default value):

Slide 8

Slide 8 text

Interactive Components • Controlled Components receive values as props • Uncontrolled Components keep values in state

Slide 9

Slide 9 text

The best of both worlds • An interactive component maintains its own state • Sometimes it yields control to its parent (props) • It can be both Controlled and Uncontrolled

Slide 10

Slide 10 text

The best of both worlds: react-controllables MATTHEWWITHANM MATTHEW DAPENA-TRETTER github.com/matthewwithanm/react-controllables

Slide 11

Slide 11 text

Example: TabBar • When you click on a tab, it becomes selected • The other tabs in the bar become deselected • The selected tab is stored as state in the component

Slide 12

Slide 12 text

class TabBar extends React.Component { constructor() { super(); this.state = {selectedIndex: 0}; } handleClick(event) { const el = event.target; const index = el.parentNode.children.indexOf(el); this.setState({selectedIndex: index}); } render() { const index = this.state.selectedIndex; return (
  • Zero!
  • One!
  • Two!
); } }

Slide 13

Slide 13 text

Example: TabBar • This works fine until one day… • A new component is introduced to the site that also controls which tab is selected • Instead of pulling state management out of TabBar, make it a controllable

Slide 14

Slide 14 text

The old(ish) way: The Controllable mixin A Brief Aside About Mixins

Slide 15

Slide 15 text

–Sebastian Markbåge, who knows what idiomatic React is “…mixins (are) an escape hatch to work around reusability limitations… Idiomatic React reusable code should primarily be implemented in terms of composition and not inheritance.”

Slide 16

Slide 16 text

–Dan Abramov, while explaining what Sebastian Markbåge meant “Mixins are dead. Long live composition.” –Sebastian Markbåge, again “Another alternative to mixins… Higher Order Components.”

Slide 17

Slide 17 text

A function that takes an existing component and returns another component that wraps it. Higher-Order Component

Slide 18

Slide 18 text

The new way: The Controllable Higher-Order Component! Example: TabBar

Slide 19

Slide 19 text

class TabBar extends React.Component { handleClick(event) { if (!this.props.onSelectedIndexChange) return; const el = event.target; const index = el.parentNode.children.indexOf(el); this.props.onSelectedIndexChange(index); } render() { const index = this.props.selectedIndex; return (
  • Zero!
  • One!
  • Two!
); } } TabBar.defaultProps = {selectedIndex: 0}; TabBar = controllable(TabBar, ['selectedIndex']);

Slide 20

Slide 20 text

Always use props! • No state in TabBar* • the controllable HOC handles the magic * Technically, the newly decorated TabBar does have state. The controllable can be thought of as providing an optional binding to a per-component state store.

Slide 21

Slide 21 text

Controllable TabBar Controlled: Uncontrolled: Uncontrolled (with a default value):

Slide 22

Slide 22 text

The future way? The Controllable Decorator! Example: TabBar

Slide 23

Slide 23 text

– Sebastian McKenzie in the Babel.js 5.0 release post “Yehuda Katz' stage 1 decorators proposal allows you to elegantly compose property descriptors and metadata decoration.”

Slide 24

Slide 24 text

JavaScript Decorators! • An expression that evaluates to a function • Easily annotate and modify classes and properties • Can act like a factory, taking additional arguments at design time • Currently a Stage 1 TC39 (ECMAScript) Proposal • Supported in Babel.js 5.0! (Python style. Basically lifted straight from Python.)

Slide 25

Slide 25 text

@controllable(['selectedIndex']) class TabBar extends React.Component { static defaultProps = {selectedIndex: 0}; static propTypes = { selectedIndex: PropTypes.number.isRequired, onSelectedIndexChange: PropTypes.func, }; handleClick(event) { if (!this.props.onSelectedIndexChange) return; const el = event.target; const index = el.parentNode.children.indexOf(el); this.props.onSelectedIndexChange(index); } render() { const index = this.props.selectedIndex; return (
  • Zero!
  • One!
  • Two!
); } }

Slide 26

Slide 26 text

HZDG.COM LETTERTWO ERIC ELDREDGE LETTERTWO@GMAIL.COM HZDG PHOTO MISSING

Slide 27

Slide 27 text

react-controllables https://github.com/matthewwithanm/react-controllables Another alternative to mixins…Higher Order https://twitter.com/sebmarkbage/status/565657028665016321 JavaScript Decorators Proposal https://github.com/wycats/javascript-decorators Mixins Are Dead. Long Live Composition https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order- Babel.js 5.0 Release Announcement http://babeljs.io/blog/2015/03/31/5.0.0/ Props vs State https://speakerdeck.com/lettertwo/props-vs-state