Editing Labels

In notebook:
Building Modern Web Apps
Created at:
2016-01-29
Updated:
2016-01-29
Tags:
libraries JavaScript React Ampersand
Let's talk about forms first.

The concept of React is to always match the state of your app with the DOM. This has some implications for html forms. If you change an input field in a form, you break this concept: the dom and the state are no longer in sync.
So React won't let you edit an input field that has a ​value​ attribute added. Unless you specify what you want to do with the changes.
In React there are controlled (if you specify a ​value​) form inputs and uncontrolled form inputs.
  // ****     components/label-item.js        ****
import React form 'react'
import ampersandMixin form 'ampersand-react-mixin'

export default React.createClass({
    mixins: [ampersandMixin]
    
    onDeletClick (event) { ... }
    
    onEditClick () { ... },
    
    onCancelClick () { ... },
    
    render () {
        const {label} = this.props
        const cssColor = '#' + label.color
        let content
        
        if (label.editing) { 
            content = (
                <form className='label'>
                    ...
                    // ++++ 1. add a default value to the input label
                    // ++++ 2. we also add an onChange handler
                    <input name='name' type='text' value={label.name} onChange={this.onNameChange} />
                </form>
            )
        } else {
            content = (
                <div className='label'>
                    ...
                </div>    
            )
        }
        return (<div>{content}</div>)
    }
})  
In normal W3C spec, the onchange event happens on blur (move out of the field). Here every time the value changes there's the event fired.

The problematic of two-way binding

In Angular: as soon as you edit something you edit the model. But if the user clicks 'cancel', I have to revert this somehow.
He argues that form editing is an in-between state. You don't want to commit the change until the user is done editing (and it's validated).

React lets you track component-specific changes. State in a React component.

We will duplicate the state as a state of the component. getInitialState​ method gives you the initial state of the component.
  // ****     components/label-item.js        ****
import React form 'react'
import ampersandMixin form 'ampersand-react-mixin'

export default React.createClass({
    mixins: [ampersandMixin]
    
    onDeletClick (event) { ... }
    
    onEditClick () { ... },
    
    onCancelClick () { ... },
    
    // ++++ 1. define what happens in getInitialSate
    getInitialState () {
        const {name, color} = this.props.label
        
        return {
            name: name,
            color: color
        }
        // so this is the internal state of the component
        // it gets run on the initialising 
    },
    
    // ++++ 2. onNameChange handler
    onNameChange (event) {
        // update the component state
        // note: event is not raw the dom event but a simulation
        this.setState({ // it's a React method, will re-render as well 
            name: event.target.value
        })
    },
    
    render () {
        const {label} = this.props
        const cssColor = '#' + label.color
        let content
        
        if (label.editing) { 
            content = (
                <form className='label'>
                    ...
                    // ++++ 3. now we can use the component state
                    <input name='name' type='text' value={this.state.name} onChange={this.onNameChange} />
                </form>
            )
        } else {
            content = (
                <div className='label'>
                    ...
                </div>    
            )
        }
        return (<div>{content}</div>)
    }
})  
React refs: it's a shortcut to reference an element (they, Henrik, others never really used it)