React: Class Component VS Function Component with Hooks
Tags: react, javascript, reacthooks, functioncomponents
Published: 2020-01-03 21:16:40

## Class Component

Before React Hooks, when we want to create a dynamic component, we have to create a class component and use lifecycle methods to change states to make it reusable and encapsulate.

By creating an ES6 class, the class needs to extend ``React.Component`` with a ``render`` method in it, which will return the JSX markups. Also, we need to assign the initial state in the constructor with ``this.state``. As an example, here we create a simple clock component with class. To make the clock working, we have to add ***__Lifecycle Methods__*** to our Class. We put elements into the DOM, it is called ``mounting`` in React. Same, We remove elements from the DOM, it is called ``unmounting``. In React, mounting a component will invoke the following four build-in methods:

- constructor()
- getDerivedStateFromProps()
- render()
- componentDidMount()

More information please read from [React Doc: Commonly used lifecycle methods](https://reactjs.org/docs/react-component.html#commonly-used-lifecycle-methods)

In our example, we set the initial state in the constructor and defined ``componentDidMount()`` to set the time every second. So the clock will update the state every second with the current time. 

```js
class ClockUsingClass extends React.Component {
    constructor(props) {
        super(props)
        this.state = { date: new Date() }
    }

    componentDidMount() {
        this.time = setInterval(() => {
            this.changeTime()
        }, 1000)
    }

    componentWillUnmount() {
        clearInterval(this.time)
    }

    changeTime() {
        this.setState({ date: new Date() })
    }

    render() {
        return (
            <div className="clock">
                <h1>Hello! This is a class component clock.</h1>
                <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
            </div>
        )
    }
}
```

{% codesandbox 888yp %}

Obviously we can see, for a class-based component, we need several steps to make it work with state-changing:
1. Create a class with ``constructor(props)`` and ``render()`` methods.
2. Set initial state with ``this.state`` statement in the constructor.
3. Use ``this.setState()`` to update states.
4. Use lifecycle methods like ``componentDidMount()``, ``componentWillUnmount()``, ``componentDidUpdate()`` etc. to change states


## Function Component with hooks

Hooks are a new addition in React 16.8. The most useful feature of Hooks is that it allows using state without using class. 

There are two most commonly used hooks: the state hook -- ``useState`` and the effect hook -- ``useEffect``. 

State hook allows you to add states in the function component. Instead of setting an initial state with ``this.state`` statement in the constructor, we can import ``{ useState }`` from react, which will allow you to set the initial state as an argument. State hook will return a pair of values: the current state and a function that updates it. Usually, we will use ``useState`` like this:

```js
    const [time, setTime] = useState(new Date())
```

Effect hook will get invoked with the first DOM updating. We can pass in a function in ``useEffect``, and every time the DOM gets updated, the function in ``useEffect`` will get invoked too. Also, the effect hook allows you to pass in an array as the second argument, which contains all the dependencies that will trigger the effect hook. if any of the dependencies changed, the effect hook will run again. This feature provides us a more efficient way to make an Ajax request. Instead of making the request every time with DOM updates, you can pass in dependencies that only make the request while these values change.
``useEffect`` can be used like:

```js
    useEffect(() => {
        setInterval(() => {
            changeTime()
        }, 1000)
    })
```

So, here we re-write the clock we created above with hooks

```js
const ClockUsingHooks = props => {
    const [time, setTime] = useState(new Date())

    const changeTime = () => {
        setTime(new Date())
    }

    useEffect(() => {
        const tick = setInterval(() => {
            changeTime()
        }, 1000)
        return () => clearInterval(tick)
    })
    return (
        <div className="clock">
            <h1>Hello! This is a function component clock.</h1>
            <h2>It is {time.toLocaleTimeString()}.</h2>
        </div>
    )
}
```

{% codesandbox iy9v7 %}


## Summary

Comparing with these two ways to create a component, we can clearly see that hooks need less code and it is more clear to read and understand. Hooks give us a more efficient way to replace lifecycle methods. 

Check out the repo to make a simple clock [here](https://github.com/danielleye/simple-react-clock)