Implementing ToggleAll

In notebook:
FrontEndMasters React
Created at:
2016-06-17
Updated:
2016-06-17
Tags:
libraries React JavaScript
Now we just need to implement the toggle all part (the parent component). Luckily now the state is passed upwards.
  var App = React.createClass({
    getInitialSate () {
        return {
            toggleAll: true,
            toggleStates: {
                jerk: true,
                thai: false
            }
        }
        
    },
    
    toggleAll () {
        // 1. ++-- change here
        // ---- console.log('uh what now')
        var { toggleStates, toggleAll } = this.state;
        // create an object like this.state.toggleStates but set all keys to either true all false
        var newStates = Object.keys(toggleStates).reduce((newStates, key) => {
            newStates[key] = !toggleAll
            return newStates;
        }, {});
        this.setState({
            // flip toggleAll as well
            toggleAll: !toggleAll,
            toggleStates: newStates
        })
    },
    
    handleToggle(id) {
        var { toggleStates } = this.state;
        toggleStates[id] = !toggleStates[id];
        this.setState({ toggleStates })
    },
    
    
    render () {
        return (
            <div>
                <h1>Props v. State</h1>
                <button onClick={this.toggleAll}>Toggle All</button>
                <div style={{margin: '10px 0'}}>
                    <ContentToggle isOpen={this.state.toggleStates.jerk} summary="Jerk Chicken">
                        <p>It was delicious</p>
                    </ContentToggle>
                    
                    <ContentToggle isOpen={this.state.toggleStates.thai} summary="Thai">
                        <p>It was probably good too</p>
                    </ContentToggle>
                </div>
                
            </div>    
        )
    }
});
- Shouldn't we clone the state object if we modify it?
- Yes, if we really want to be pure about it we can. This would avoid some mutation.
      handleToggle(id) {
        var { toggleStates } = clone(this.state.toggleStates);
        toggleStates[id] = !toggleStates[id];
        this.setState({ toggleStates })
    },
Now it almost works, except when they (ContentToggles) are all open the toggleAll button doesn't close them all. 
Copies ​handleToggle​ from his notes.js file:
    handleToggle (id) {
    var { toggleStates } = this.state;
    toggleStates[id] = !toggleStates[id];
    this.setState({ toggleStates });
    var keys = Object.keys(toggleStates);
    var areOpen = keys.filter(key => toggleStates[key]);
    // if ALL of othem are open
    if (areOpen.length === keys.length) {
      this.setState({ toggleAll: true });
    }
    // if NONE of them are TRUE
    else if (areOpen.length === 0) {
      this.setState({ toggleAll: false });
    }
  },
Explains ​Array.prototype.reduce​. 

There are about seven React life cycle hooks. Need to look up in the documentation.

The advantage of pure components is that you don't have to worry about synchronising your states between components. Of course, the state does have to live somewhere (on the top)...