Binding to a Model

In notebook:
Building Modern Web Apps
Created at:
2016-01-25
Updated:
2016-06-12
Tags:
JavaScript libraries React Ampersand
Connecting React to Model updates
We need something that tells React that something has changed.

We need a strategy to handle the case where the data has changed. E.g. the login element (username). At rendertime it's probably undefined. We need to update it when the user logs in.

There's a generic a change event that gets fired when anything changes.
Their (developers at Ampersand) strategy is that when a model or collection is passed to a React component, register a handler that will update when the model or collection have changed. Done by adding a mixin.
  // **** layout.js ****
import ...
// ++++ 1. import ampersand mixin
import ampersandMixin from 'ampersand-react-mixin'

export default React.createClass({
    displayName: 'Layout',
    // ++++ 2. add the mixin
    // that can listen to changes
    // mixins are part of React
    // see below for more explanation
    mixins: [ampersandMixin]

    render () {
        return (
            <NavHelper className="something">
                <nav className="top-nap">
                    ...
                    {this.props.children}
                </nav>
            </NavHelper>
            )
    }
})
The React mixin :
When this component mounts to the DOM it runs a simple function that checks if any it's properties are models or collections and registers a change handler for those. If any of these properties change, force an update.
These events are debounced, in one event loop the force update is only called once even if the event was fired five times.

Then with the help of ampersandMixin we pass a model to the layout in router.js
  // **** router.js ****
import ...

export default Router.extend({
    renderPage (page, opts = {layout:true}) {
        if(opts.layout) {
            page = (
                // ++++ 1. add me={app.me}
                // we're passing a model
                <Layout me={app.me}>
                    {page}
                </Layout>
            )
        }
    }
    
    routes: { ... },
    public () { ... },
    repos () { ... },
    login () { ... },

    authCallback (query) { ... },

    logout () { ... }   
})
Now, any time me changes it will force a render. So now in the React component you would reference it as ​this.props.me.propertyname​ (e.g. ​this.props.me.login​)
Or use ES6 destructuring ​var {me} = this.props​ Then just use ​me.login​ 
  // **** layout.js ****
import ...
// ---- 3. can remove the app import
// since we're no longer using it
// import app from ampersand-app // deleted

export default React.createClass({
    displayName: 'Layout',

    mixin: [ampersandMixin]

    render () {
        // ++++ 1. add me as a destructured var
        const {me} = this.props
        return (
            <NavHelper className="something">
                <nav className="top-nap">
                    ...
                    // ++++ 2. use the login name
                    <li className='pull-right'><a href="/logout">Logout<a> {me.login}</li>
                    ...
                    {this.props.children}
                </nav>
            </NavHelper>
            )
    }
})

The mixin method

React lifecycle methods
These are listed on the React documentation site
facebook.github.io/react/docs/component-specs.html
e.g. ​componentWillMount​ or ​componentDidMount​ 
if you define these functions (method) in a component these will run at that lifecycle 
moment.

The ​mixin​ is actually a part of ampersand: ampersand-react-mixin.js (see github)

It forces a change local to that component. We specify very precisely which component needs to update (to diff).

My note: ampersand-react-mixin will listen to models or collections passed to ​this.props​. In the above example when we call ​<Layout me={app.me}>​ in router.js, we’re passing app.me to ​this.props​. No extra configuration is necessary.

Flux pattern to connect models to React

There's no standard way in React to observe models and react to it. There's the flux design pattern.
Any mutations or change happen through mutations. Mutations are states that you register at the application level. Then you have stores where your data lives (that you get from the server, etc.) and a central dispatcher that fires events. All the stores listen to actions and in the end you get a single change event that triggers the rerender.

ALT is an implementation, one of he cleanest, simplest implementaton