I'm going to convice you using React Hooks

(If you are not using them yet, of course).

Quick intro

Lately, I've been working on a React app as part of my job. We are working with the usual React + Redux, with the old "class" way (which are still completely valid, don't get me wrong). But you know, hooks have been around for quite a while, and they are amazing. Let me show you why they are, and give me a chance to convince you using them.

Redux

If you have worked with Redux before, you know the drill:

  • Create the store
  • Wrap your application within the store
  • Connect the component with the HOC (Higher-Order-Component)
  • Create the mapStateToProps and mapDispatchToProps functions and applied theses to the connect ...

Pretty basic things that we do everyday, you may even have some VSC snippets to help you out.

State

Let's leave Redux for a second. How would you declare a state ?

  • Create your component
  • Call the constructor and the super
  • Create your this.state variable and fill it with values

~ Wait, in a real world exemple, there is more ...
~ You're right, let's add some lifecycles.

Lifecycles

In every real apps, you will have to gather some datas from your API endpoints. The best place to do so is within the ComponentDidMount. Sometimes, you even need to apply things on certains updates, it's where ComponentDidUpdate is coming handy. And of course you need to clean your subscriptions into a ComponentWillUnmount ...

A lot of things to remember, right ? And a lot of methods to write.

~ What if I can tell you that you can transform the 10+ lines declaration, into a 3 lines one ?
~ But, how ?!

With React Hooks feature, and this is how I'm going to convince you to give them a try.

Regular Class style exemple

Let's put everything we talked about inside this component ...

import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      // State ..
      user: {},
    };
  }

  componentDidMount() {
    // Fetch API endpoint
  }

  componentDidUpdate(prevProps, prevState) {
    // Apply effect based on changes ..
  }

  componentWillUnmount() {
    // Cancel subscriptions ..
  }

  render() {
    return <div>// Your app tree</div>;
  }
}

const mapStateToProps = (state) => {
  return {
    // Return some element from your state ..
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    //Return some functions that dispatch for you in the store ..
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

As you can see, without any logic specific code and JSX, the minimum required amount of code start to be substantial.

Functionnal Component exemple

Now the fun part, let's rewrite everything using some Hooks. Don't worry, we will do it step-by-step.

First, let's initialze your state:

import React, { useState } from 'react';

const App = () => {
  const [user, setUser] = useState({});

  return <div>// Your app ..</div>;
};

export default App;

Let's recap what is going on here. We use a React Hook called useState() which return a value, and a method to update this value. We also use the nice destructration synthax to get a super nice one liner.
(More informations on the useState here).

Next, let's add our lifecycles:

import React, { useState, useEffect } from 'react';

const App = () => {

    const [user, setUser] = useState({});

     useEffect(() => {

        // Equivalent of componentDidUpdate

        return () => // Equivalent of componentWillUnmount

    }, []); // Equivalent of componentDidUpdate.
    // It's an array of dependencies, add values there,
    // and React will re execute the useEffect whenever one of value changes

    return (
        <div>
            // Your app ..
        </div>
    )};

export default App;

Amazing, isnt it ? You can find more more infos here. But basically, React will always execute what is inside he useEffect on the first render, and will watch the value passed into the array to re-run the effect again. You'll return what you want to execute when the component unmount.

And last but not least, let's use Redux in there :

import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

const App = () => {

    const [user, setUser] = useState({});

    const dispatch = useDispatch(); // Give access to the dispatch function
    const foo = useSelector(state => state.foo); // Recover the value from the store

    useEffect(() => {

        // Equivalent of componentDidUpdate

        return () => // Equivalent of componentWillUnmount

    }, []); // Equivalent of componentDidUpdate. It's an array of dependencies, add values there, and React will re execture the useEffect whenever one of value changes

    return (
        <div>
            // Your app ..
        </div>
    )};

export default App;

The code is pretty straightforward, buy it's only some very basic usages, you can gather more infos here. But bascially, you now have access to the dispatch function, and to whatever value you want without having to mapDispatch and mapState. Without even the connect, and our component is now connected implicitely.

Conclusion

Well, nothing to conclude on, really. But take a second, and compare both code snippets. The result is stunning, you saved so much code for doing the exact same thing.
I'll link you the react official documentation here, and you can scroll down to a youtube video that does an amazing convertion from class to hooks.

Now, tell me, are you convinced to give them a try ?

Have a nice day.