Adding an Editing State

In notebook:
Building Modern Web Apps
Created at:
2016-01-28
Updated:
2016-01-29
Tags:
libraries JavaScript React Ampersand
Create file in /components 
First start with the simplest component
  // ****     components/label-item.js        ****
import React form 'react'

export default React.createClass({
    render () {
        const {label} = this.props

        return <li>{label.name}</li>
    }
})
Then you can use it in repo-detail.js
  // ****     pages/repo-detail.js    ****
import ...
// ++++ 1. import the component
import LabelItem from '../components/label-item'

export default React.createClass({
    mixins: [ampersandMixin],
    displayName: 'RepoDetail'
    
    render () {
        const {repo} = this.props
        
        return (
            <div className='container'>
                <h1>{repo.full_name}</h1>
                <p></p>
                <ul>
                {labels.map( label => {
                    // ++++ 2. then just replace with the LabelItem component
                    // make sure to pass label (this.props in the component)
                    return <LabelItem label={label}/>
                })}
                </ul>
            </div>
        )    
    }
})
Let's continue with the label-item component (this is where we will edit)

We need to add a key (so React can be efficient)

Add it for the parent:
  // ****     pages/repo-detail.js    ****
import ...

export default React.createClass({
    mixins: [ampersandMixin],
    displayName: 'RepoDetail'
    
    render () {
        const {repo} = this.props
        
        return (
            <div className='container'>
                <h1>{repo.full_name}</h1>
                <p></p>
                <ul>
                {labels.map( label => {
                    // ++++ 1. add the key
                    return <LabelItem key={label.name} label={label}/>
                })}
                </ul>
            </div>
        )    
    }
})
Talks about different ways to obtain a key

You have to set the key, where you're iterating (so in this case repo-details.js) and not in the component (label-item.js) for React to be able to take advantage of it.

Talks about ES6 spread feature to add dynamically the properties
There will be two modes on the label-item a) viewing (display) the label or b) editing it.
The layout will branch
  // ****     components/label-item.js        ****
import React form 'react'

export default React.createClass({
    render () {
        const {label} = this.props
        //  ++++ 1. the branching
        let content
        
        // editing...
        if () { 
            content = (
                <form className='label'>
                    ...
                </form>
            )
        } else {
            // displaying
            content = (
                <div className='label'>
                    ...
                </div>    
            )
        }
        // ++++ 2. return it inside a div (see below)
        return (<div>{content}</div>)
    }
})
React doesn't like if we swap out the root element ( ​<form>​ -> ​<div>​ ).
Better to keep this in a separate variable.
Talks about editing mode and where to keep it in the state? Is it local to the element or a global state?
If global you have to communicate it (messaging) if it's local to the component, keep it local!

We don't want to persist the editing state (just like the authorisation token before). But we might care about this state in other parts of the app.
  // ****     label.js            ****
import Model from 'ampersand-model'

export default Model.extend({
    props: {
        name: 'string',
        color: 'string'
    },
    
    // ++++ 1. add editing state
    // to the session
    session: {
        editing: {
            type: 'boolean',
            // note: default property
            default: false
        }
    }
})
No we can use this state in label-item component
  // ****     components/label-item.js        ****
import React form 'react'

export default React.createClass({
    render () {
        const {label} = this.props
        let content
        
        // ++++ 1. add the editing session state
        if (label.editing) { 
            content = (
                <form className='label'>
                    ...
                </form>
            )
        } else {
            // displaying
            content = (
                <div className='label'>
                    ...
                </div>    
            )
        }
        return (<div>{content}</div>)
    }
})

Why editing is in session and not in props

Session state stays local to the browser, pops will be sent to the server. 
This is specific to ampersand. In Backbone you have to override the serialisation to not to include properties.