Setting the default state

In the Component constructor, initialize this.state. For example the BlogPostExcerpt component might have a clicked state:

class BlogPostExcerpt extends Component {
  constructor(props) {
    super(props)
    this.state = { clicked: false }
  }

  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
      </div>
    )
  }
}

Accessing the state

The clicked state can be accessed by referencing this.state.clicked:

class BlogPostExcerpt extends Component {
  constructor(props) {
    super(props)
    this.state = { clicked: false }
  }

  render() {
    return (
      <div>
        <h1>Title</h1>
        <p>Description</p>
        <p>Clicked: {this.state.clicked}</p>
      </div>
    )
  }
}

Mutating the state

A state should never be mutated by using

this.state.clicked = true

Instead, you should always use setState() instead, passing it an object:

this.setState({ clicked: true })

The object can contain a subset, or a superset, of the state. Only the properties you pass will be mutated, the ones omitted will be left in their current state.

Why you should always use setState()

The reason is that using this method, React knows that the state has changed. It will then start the series of events that will lead to the Component being re-rendered, along with any DOM update.

State is encapsulated

A parent of a Component cannot tell if the child is stateful or stateless. Same goes for children of a Component.

Being stateful or stateless (class-based or functional) is entirely an implementation detail that other components don’t need to care about.

This leads us to Unidirectional Data Flow

Unidirectional Data Flow

A state is always owned by one Component. Any data that’s affected by this state can only affects Components below it: its children.

Changing a state on a Component will never affects its parent, or its siblings, or any other Component in the application: just its children.

This is the reason many times the state is moved up in the Components tree.

Moving the State Up in the Tree

Because of the Unidirectional Data Flow rules, if two components need to share a state, the state needs to be moved up to a common ancestor.

Many times the closest ancestor is the best place to manage the state, but it’s not a mandatory rule.

The state is passed down to the components that need that value via props:

class Converter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { currency: '€' }
  }

  render() {
    return (
      <div>
        <Display currency={this.state.currency} />
        <CurrencySwitcher currency={this.state.currency} />
      </div>
    )
  }
}

The state can be mutated by a child component by passing a mutating function down as a prop:

class Converter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { currency: '€' }
  }

  handleChangeCurrency = (event) => {
    this.setState({ currency: this.state.currency ===
      '€' ? '$' : '€' })
  }

  render() {
    return (
      <div>
        <Display currency={this.state.currency} />
        <CurrencySwitcher
          currency={this.state.currency}
          handleChangeCurrency={this.handleChangeCurrency} />
      </div>
    )
  }
}

const CurrencySwitcher = (props) => {
  return (
    <button onClick={props.handleChangeCurrency}>
      Current currency is {props.currency}. Change it!
    </button>
  )
}

const Display = (props) => {
  return (
    <p>Current currency is {props.currency}.</p>
  )
}

The result