DEV Community

Bradley Black
Bradley Black

Posted on

Classes or Hooks: Managing State in React

When learning to program with the React Javascript library, a central theme begins to emerge: dynamism with stability and simplicity. Modern applications are built for interaction. So much so that programs feel less like lines of code and more like living organisms. This is a useful lens for viewing React’s architecture. Like living things, React has centralized higher-level logic and functionality. One of the key pieces of this centralized structure is known as state.

State is used to maintain all the parts of an application that have dynamic potential. Elements in the DOM are mere sensory triggers that relay user behavior and display information dictated by state. So how does one interact with their application’s state?

Prior to the release of React 16.8, state was a feature exclusive to class components. Class components, unlike their functional counterparts, could access state on the React component constructor method. However, 16.8 now allows developers to utilize state in functional components as well. This is done with a set of methods totally distinct from those used by classes. It’s important to remember that these methods are exclusive to each type of component! In other words, it’s impossible to implement class state methods on functional components, and vice versa.

Structure of State

Not only are the class and functional state methods distinct, the structure of state itself is unique to each component. For class components, state is an object. The state object’s keys represent dynamic elements in an application, and the values of these keys reflect the current state of each element.

When accessing state in functional components, you bypass this object structure and engage with the values directly. Values held in state are simply assigned to a variable, and through a unique function that couples closely to the variable, its value can be manipulated.

setState of Class Components

Setting/changing state of class components is accomplished with the following syntax:

class Pizza extends React.Component {
  constructor(props) {`
    super(props);
    this.state = {
      customer: '',
      size: '',
      toppings: [],
      count: 0,
    };
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange() {
    this.setState({
      customer: 'Isidro',
      size: 'medium',
      toppings: ['spinach', 'musrooms', 'onions', 'garlic'],
      count: this.prevState.count + 1
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

For this example, the values in the handleChange method have been hard-coded for simplicity. The setState method must return an object. The object will reference a key that has been added to state, and it will reassign the state value to the one being returned. Conveniently, a return object that only contains a single key/value pair will not cause other key/values in state to be removed. Only the key returned by the setState method will be affected.

In a situation where the current value of state must be accessed to properly reassign state (represented in this example by the customer’s customerLoyaltyCount), prevState is passed into setState as an argument, and all state properties can be referenced on the prevState object.

To summarize class components: a key/value is initialized on the this.state object, and it is manipulated with the setState method.

useState of Functional Components

Functional components acknowledge state with es6 destructuring syntax and the useState method:

function Pizza() {
  const [customer, setCustomer] = useState('')
  const [size, setSize] = useState('')
  const [toppings, setToppings] = useState([])
  const [count, setCount] = useState(0)

  const handleChange= () => {
    setCustomer('Isidro')
    setSize('medium')
    setToppings(['spinach', 'musrooms', 'onions', 'garlic'])
    setCount(count + 1)
  }
}
Enter fullscreen mode Exit fullscreen mode

useState initializes a property to state. The argument provided sets the initial state value. It returns a tupple with the state value at index 0 and a function to alter this value at index 1. Destructuring allows programmers to assign this value/function pair to unique variable names. So, instead of using setState to access state, and then specifying the property that needs to be changed, one simply calls the named function that achieves this result.

Summary

Adding state to functional components has given developers an alternate way to add interactivity though React. Also, because functional components don’t utilize constructors or bindings, the syntax is much cleaner than that of class components. This exemplifies how React aims to simplify and super-charge the tools programmers use to make modern applications.

Top comments (0)