React 16.8 introduced hooks, and they are awesome.
Hooks make it easy to manage states without having to define classes.
Without hooks, if you want to manage the state of a component you need to define a component as a class and explicitly initialize a state.
You also need to reference it by calling this which adds complexity that we don't need.
Here's an example of what a traditional component could look like:
      
    class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      apples: 0
    };
  }
  render() {
    return (
      <div>
        <h1>You have {this.state.apples} apples</h1>
        <button onClick={() => this.setState({ apple: this.state.apples + 1 })}>
          Add an apple
        </button>
      </div>
    );
  }
}
We create our component and give it a constructor that initializes the state we want to manage. It's not much but this boilerplate can add up over time, and we have other ways to add state to a component.
Instead, we can use hooks which remove the need for the class component to store state as an attribute. We can initialize the state and create a function to update the state in a single line, and we no longer need to call this.
Here's what the functional component would look like:
import React, { useState } from 'react';
function Counter() {
  const [apples, setApples] = useState(0);
  return (
    <div>
      <h1>You have {apples} apples</h1>
      <button onClick={() => setApples(apples + 1)}>
         Add an apple
      </button>
    </div>
  );
}
Initializing State
React allows you to import useState.  This hook takes the initial state as an argument and returns both the state and a function to update the state.
Where a traditional class component would need to define a constructor to initialize it's state:
constructor(props) {
    super(props);
    this.state = {
      apples: 0
    };
  }
We can initialize state in a much cleaner way with the useState hook:
const [apples, setApples] = useState(0);
The initial state of apples will be set to the value we pass into useState, in this example 0.
How to Update State with State Hooks
In a class component, you would update your state by calling this.setState() and passing the new state as the argument.
Functional components still work in a similar way. There is less typing needed and unlike this.setState() you can see where our state's update function is defined.
Our example uses setApples() which doesn't need a call to this and we can see that we defined setApples above when we create our initial state.
Want to Learn More?
Check out the official React documentation here.