Skip to content

Practice rewriting old-school React classes using the new React hooks

Notifications You must be signed in to change notification settings

oliverjam/react-refactor-class-hooks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Refactor React classes to hooks

Hooks (e.g. useState, useEffect and more) are a relatively new React feature. Before that stateful components had to be created using JavaScript classes. It's important to be able to read class-based code since you'll probably encounter it out in the world.

Classes

Classes were added to JS with ES6. They're a special syntax for creating reusable objects with methods and properties.

They can also "extend" other classes to inherit their properties.

class Dog {
  sayName() {
    return this.name;
  }
}

class Fido extends Dog {
  name = "Fido";
}

const myFido = new Fido();
myFido.sayName(); // "Fido"
// Note the Fido class didn't define a sayName method. It was inherited from Dog

Don't worry too much about classes—they're rarely used in React anymore, and even when they were hardly any of their features were used.

Syntax

React class components are created by extending the React.Component base class:

class Counter extends React.Component {
  render() {
    return <button>Count is 0</button>;
  }
}

The render() method is the equivalent of a function component body. You return React elements from here to render them to the DOM.

Updating state

We can set a class property named state to tell React to keep track of some values. This property is always an object.

class Counter extends React.Component {
  state = {
    count: 0,
  };
  render() {
    return <button>Count is {this.state.count}</button>;
  }
}

We can access the state object via this.state.

If we want to update state we call this.setState() and pass in a new object. React will merge this object with the existing state:

class Counter extends React.Component {
  state = {
    count: 0,
  };
  render() {
    return (
      <button onClick={() => this.setState({ count: this.state.count + 1 })}>
        Count is {this.state.count}
      </button>
    );
  }
}

We can also store methods as properties on the class so they're reusable:

class Counter extends React.Component {
  state = {
    count: 0,
  };
  increment = () => this.setState({ count: this.state.count + 1 });
  render() {
    return (
      <button onClick={this.increment}>Count is {this.state.count}</button>
    );
  }
}

this.setState() can take a function instead of an object if you need to access the previous state value (the same as with React.useState()).

class Counter extends React.Component {
  state = {
    count: 0,
  };
  increment = () =>
    this.setState((oldState) => {
      return { count: oldState.count + 1 };
    });
  render() {
    return (
      <button onClick={this.increment}>Count is {this.state.count}</button>
    );
  }
}

Effects

Classes don't have a built-in way to deal with side-effects. Instead you have to hook into their "lifecycle" using specially named methods. These function are called at various points by React as it creates your component, puts it into the DOM, updates it or removes it.

For example to run some code when React is ready to render your component to the page we use componentDidMount:

class Pokemon extends React.Component {
  state = {
    data: null,
  };
  componentDidMount() {
    fetch("https://pokeapi.co/api/v2/pokemon/pikachu")
      .then((res) => res.json())
      .then((data) => this.setState({ data }));
  }
  render() {
    if (!data) return <div>Loading...</div>;
    return <div>{data.name}</div>;
  }
}

To run some code when your component updates (i.e. is passed new props or setState is called) you can use componentDidUpdate(). To clean up after your component (i.e. cancelling timers or removing global event listeners) you can use componentDidUnmount(). There are quite a lot of these and you probably won't need them all.

Exercise

  1. Clone the project and run npm i
  2. npm t to run the test watcher
  3. Rewrite src/Counter.js to use hooks instead of classes
  4. Rewrite src/Keyboard.js to use hooks instead of classes
  5. Rewrite src/Pokemon.js to use hooks instead of classes
  6. Keep all the tests passing!

About

Practice rewriting old-school React classes using the new React hooks

Resources

Stars

Watchers

Forks