Proper use of Hooks

The initial scenario in which the author used React Hooks was to refactor an existing Class component using Hooks.

Rewriting the Class component is not too difficult

  1. useuseStatealternativethis.state
  2. useuseCallbackAn alternative to Class
  3. useuseEffectReplace life cycle functions

First, let’s take a look at a component implemented using Class that supports adding and deleting lists (sorry, only adding).

Edit On CodeSandbox

Refactoring component

Let’s try using a Class component as a Function + Hooks component based on the above violence output and the HooksAPI provided on the official site.

Edit on CodeSandbox

It looks like nothing’s wrong, and it feels like you’ve refactored your code. But there is always a little unease in my heart, where does this unease come from?

Use React Hooks. Write a block of code in a function. It’s not as logical as OOP.

And if you think about it, it does. The refactored component code logic is all in the same function, which looks illogical, poorly readable, and difficult to maintain.

Such a simple component is so messy after rewriting, the logic of a more complex component, is a bigger pile of pasta

Code optimization

Do not use React Hooks? Does it really not smell good? !

Considering that my code ability is the worst, there must be something wrong with my posture. Let’s see if we can keep optimizing!

1. Encapsulate semantic useEffect

In the code above, useEffect is used to simulate the life cycle for componentDidMount. React officially recommends using multiple useeffects to do different things, not all together. So we can encapsulate that.

// useMount sourcecode
import { useEffect } from 'react';
const noop = (a)= > {};
export function useMount(mount, unmount = noop) {
    useEffect((a)= > {
        mount();
        return (a)= >{ unmount(); }; } []); }Copy the code
// use case
export default function Demo(props) {
    useMount((a)= > {
        // do something
        // after didMount
    });
}

Copy the code

2. Wrap Hooks

In the above component, useState is used, and setXXX methods that change State are called in add, edit, delete, and so on.

For data-actions like this that are related, we can wrap our own Hooks

import { useState, useCallback } from 'react';

export function useList(initial = []) {
    const [list, setList] = useState(initial);

    const add = useCallback(data= > {
        // setXXX gets the latest state data after using the function
        setList(list= >[...list, data]); } []);const edit = useCallback(data= > {}, [list]);
    const deleteOne = useCallback(data= > {}, [list]);

    return [list, add, edit, deleteOne];
}

Copy the code

The above data structure-manipulation method is only the simplest solution. More usage methods and abstractions will be used on a case-by-case basis.

So after that encapsulation,

export default function Demo() {

    const [list, add, edit, deleteOne] = useList([]);
    const handleAdd = useCallback((a)= > {
        add({
            title: `local data ${list.length}`.description: 'description test'}); } []);const handleEdit = useCallback((a)= >{} []);const handleDelete = useCallback((a)= >{} []); usetMount((a)= > {});
    / /...
    // Nothing else
}

Copy the code

methodology

Methodology mainly deals with the problem of “how to do”.

The following is a summary of my own practice on React Hooks. If you have better ideas, please do so.

The methodology mentioned here is how to properly apply React Hooks when using the function component.

First, let’s return our attention to the function component originally mentioned, which is actually the data => view, a special set of input and output functions.

v = f(p)
Copy the code

Function components and React Hooks embody the idea of functional programming:

Functional programming is a programming paradigm that treats computer operations as functions and avoids the use of program states and mutable objects. Among them, lambda calculus is the most important foundation of the language. Furthermore, a function of the lambda calculus can accept functions as inputs (arguments) and outputs (outgoing values). Compared with instruction programming, functional programming emphasizes the results of program execution rather than the process of execution. It advocates gradual calculation of results by using several simple execution units, and deduces complex operations layer by layer rather than designing a complex execution process.

Mentioned above are processes like data -> View -> SideEffect.

Each render is caused by a different situation -> data changes -> View updates -> Executing SideEffect. This is a mainline render flow, which can be restructured as follows:

Each render === multiple (data, operation instructions, side effects) => View => SideEffect processing

We need to care more about the tuple (data, instructions, side effects), how to combine multiple tuples into a single data -> view -> SideEffect in this rendering process is what the React Fiber architecture implements. This mental operation is addressed by the React framework. We just need to get the encapsulation (data, action instructions, side effects) right.

This is what we can do with React Hooks, and how we can properly encapsulate the methodology that uses React Hooks.

Personally, I think countdown is a good example

import React, { useState, useCallback, useEffect, useRef } from "react";

export function useCount() {
  const [count, setCount] = useState(0);
  const timer = useRef(null);

  useEffect((a)= > {
    timer.current = setTimeout((a)= > {
      if (count > 0) {
        setCount(count - 1); }},1000);

    return (a)= > {
      clearTimeout(timer.current);
    };
  }, [count]);

  const startCount = useCallback(count= >{ setCount(count); } []);const stopCount = useCallback((a)= >{ clearTimeout(timer.current); } []);return [count, startCount, stopCount];
}

Copy the code

We use useCount as a wrapped Hook, providing data ->count, operation ->startCount, and internally using useEffect to encapsulate the logic of using setTimeout countdown.

Edit on CodeSandbox

conclusion

This paper focuses on how to properly use ReactHooks, and proposes the methodology of writing function component +ReactHooks.

Encapsulation Hooks are also from a practical standpoint of being extensible and maintainable. This article also reminds me not to write Hooks for Hooks’ sake.