DEV Community

JesseNReynolds
JesseNReynolds

Posted on

React Class vs Functional Components, Part 2: State

State

In the before times we only had access to state methods in class components, and a controlled form for first and last name looked like this.

class OurComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      givenName: '',
      surName: ''
    };
  }

    handleGivenNameChange = event => {
    this.setState({
      givenName: event.target.value
    })
  }

  handleSurNameChange = event => {
    this.setState({
      surName: event.target.value
    })
  }

  handleSubmit = event => {
    //not relevant here, nothing will change in the body of 
    //this function unless you're dealing with a callback  
    //that references state or props
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit(event)}>
        <input type="text"
        onChange={event => this.handleGivenNameChange(event)} 
        value={this.state.givenName} />
        <input type="text"
        onChange={event => this.handleSurNameChange(event)} 
        value={this.state.surName} />
      </form>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

But now we can use hooks to write functional components that are stateful. We need to import useState, and the we set one or more state variables to track state, and and a name for the function to update the state. Those variables can be directly referenced, and we can call the function to set the new value.

import React, { useState } from 'react';

function OurComponent(props) {

    const [givenName, setGivenName] = useState('')

    const [surName, setSurName] = useState('')

    const handleGivenNameChange = event => {
      setGivenName(event.target.value)
    }

    const handleSurNameChange = event => {
      setSurName(event.target.value)
    }

    const handleSubmit = event => {
      //not relevant here, nothing will change in the body of 
      //this function unless you're dealing with a callback  
      //that references state or props
    }

    render() {
      return (
        <form onSubmit={event => handleSubmit(event)}>
          <input type="text"
          onChange={event => handleGivenNameChange(event)} 
          value={givenName} />
          <input type="text"
          onChange={event => handleSurNameChange(event)} 
          value={surName} />
        </form>
      )
    }
  }
Enter fullscreen mode Exit fullscreen mode

We haven't reduced our number of lines by that much, but we have made everything more compact; referencing givenName is certainly more concise than referencing this.state.givenName. In fact, now that our variables are more terse, we could do a little refactoring here that would have left some longer, hard to read lines in the class component...

import React, { useState } from 'react';

function OurComponent(props) {

    const [givenName, setGivenName] = useState('')

    const [surName, setSurName] = useState('')

    const handleSubmit = event => {
      //not relevant here, nothing will change in the body of 
      //this function unless you're dealing with a callback  
      //that references state or props
    }

    render() {
      return (
        <form onSubmit={event => handleSubmit(event)}>
          <input type="text"
          onChange={event => setGivenName(event.target.value)} 
          value={givenName} />
          <input type="text"
          onChange={event => setSurName(event.target.value)} 
          value={surName} />
        </form>
      )
    }
  }
Enter fullscreen mode Exit fullscreen mode

This wouldn't be a good refactor if you were controlling to prevent bad inputs or to do anything complex, but we can see the sorts of refactors that having shorter ways to reference and change state opens up

Come back next week for useEffect, and how it can replace the class based lifecycle methods like componentDidMount, componentWillUpdate, etc.

Top comments (0)