Intro to React

State

State in React

  • Components are state machines
  • A stateful component will declare its initial state, and then use the special, asynchronous this.setState to update state
    • Why do you need to use this.setState? Because every time you do, React will update the view in that wonderful, efficient way that it does
    • this.state, on its own, should be considered immutable

Virtual DOM

  • Remember that React is like another API for the DOM -  except it's very smart
  • With React, you never interact directly with the DOM - only with React's virtual DOM
  • Every time you use ReactDOM.render, React builds a DOM tree out of React Elements, similar to the actual DOM, and renders the view using its virtual DOM

Rendering

  • When you use setState, React build a brand new virtual DOM tree
    • React then diffs this tree with the old DOM tree, and makes the minimal adjustments necessary to render the updated view
    • This is one of React's killer features - it's the reason why React renders so quickly!

React Principles

  • Whenever possible, write stateless components
    • A higher-level, stateful component will pass down its state as props to its children
    • This lets props be the source of truth for those components
  • State should be minimal
  • State should contain data that a component's event handlers may change to trigger a UI update 
  • State should not contain computed data, other React components, or duplicated data from props
/* Using createClass */

const Heart = React.createClass({
    getInitialState: function () {
        return { hearted: false };
    },
    heart: function () {
        this.setState({ hearted: true });
    },
    render: function () {
        return <i className="fa fa-heart" onClick={this.heart}></i>
    }
});

I Heart React

/* Using classes */

class Heart extends React.Component {
    constructor (props) {
        super(props);
        this.state = { hearted: false };
    }

    heart () {
        this.setState({ hearted: true });
    }

    render () {
        return <i className="fa fa-heart" onClick={this.heart}></i>
    }
});

I Heart ES6

Async

Lifecycle

  • This is all well and good, but you might be wondering how we get state to hold data from an AJAX request
    • In Angular, we have resolve blocks
    • React does not have an equivalent. The React team recommends making AJAX requests from the ComponentDidMount lifecycle hook
  • This is a lifecycle hook provided by react to run once the component mounts
  • Note that the render method will still be invoked before it has data from your AJAX call

Simple AJAX

class Posts extends React.Component {
    constructor (props) {
        super(props);
        this.state = { posts:[] };
    }

    componentDidMount () {
        axios.get('/api/posts')
            .then(res => res.data)
            .then(data => this.setState({
                posts: data
            });
    }

    render () {
        return (
            <div>
                {
                    this.state.posts.map(post => {
                        return <h1>{post.content}</h1>
                    });
                }
            </div>
        );
    }
});

What gives?

  • There's also a lifecycle hook called ComponentWillMount, which executes before the component renders...that seems better for AJAX, right?
    • Maybe not...ComponentWillMount runs on the server, if you're doing server-side rendering, but ComponentWillUnmount doesn't
      • Memory leaks, separation of concerns, weird async bugs, etc.
  • That being said, ideas like Flux have different solutions (which we'll not cover here just yet). TLDR: ComponentDidMount !== Resolve

Resources

  • https://facebook.github.io/react/index.html
  • http://stackoverflow.com/questions/27139366/why-do-the-react-docs-recommend-doing-ajax-in-componentdidmount-not-componentwi

Intro to React - State

By Tom Kelly

Intro to React - State

  • 1,273