background

I was very honored to attend vueconf held in Shanghai on June 8th, during the introduction of Vue3.0 by UVU himself, I saw some new features of Vue3.0, among which the most important RFC is Vue function-based API RFC. Not long ago, I happened to study React Hook, and I felt that people of react Hook have similar ideas, so I wanted to summarize the idea of hook. At the same time, I saw that many people introduced hook separately. Of course, it may be related to vue3.0’s explanation of this feature just came out. So, lets begin ~

What is a hook

First of all, we need to understand what a hook is. Take the introduction of React as an example.

It lets you use state and other React features without having to write a class

The React component was written mostly as a class component prior to 16.8. The Class-based component react provides more operability, such as its own state and lifecycle implementation. Class support is higher for complex logic:

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date(a)}; } componentDidMount() {// do sth... }

  componentWillUnmount() { // do sth... }
  
  // other methods or lifecycle...
  
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>); }}Copy the code

Function Component can only have props. Function Component can only have state. In other words, it can only implement stateless component:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
Copy the code

React didn’t provide any way to set state or lifecycle actions in function components, so at the time, function components were suitable for very few scenarios. However, this changed with the hook release of version 16.8. Hook lets you use state and other React features without writing a class. Here’s an example:

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable called "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={()= > setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Copy the code

UseState is a Hook provided by React that allows you to set the desired state in the function component. It also allows you to use setState easily. React provides a variety of hooks to support different actions and actions. We’ll look at the vue hook below.

import { value, computed, watch, onMounted } from 'vue'

const App = {
  template: ` 
      
count is {{ count }} plusOne is {{ plusOne }}
`
, setup() { // reactive state const count = value(0) // computed state const plusOne = computed((a)= > count.value + 1) // method const increment = (a)= > { count.value++ } // watch watch((a)= > count.value * 2, val => { console.log(`count * 2 is ${val}`)})// lifecycle onMounted((a)= > { console.log(`mounted`)})// expose bindings on render context return { count, plusOne, increment } } } Copy the code

It is easy to see from the above example that the usage of REACT Hook is very similar to that of React Hook. Moreover, UVU also said that this RFC borrowed the idea of React Hook, but avoided some problems of React. Then, I will explain why I called this RFC of VUE hook. React Hook is a function that allows you to hook into functions such as react state and lifecycle. Vue provides a similar API that allows you to “hook” value(data in 2.x) and lifecycle functions into function components, so call it vue-hook

The significance of Hook

So, what is the significance of hook? From the beginning, the framework serves the business, and it is difficult to avoid a problem in business — logic reuse. For the same function, the same component, in different occasions, we sometimes have to write 2+ times. In order to avoid coupling, various frameworks have come up with some solutions:

  • mixin
  • HOC
  • slot

Usage of various frameworks:

  • React and Vue both used mixins (react is now deprecated),
  • Higher-order-components (HOC) react is used more, vue, nested template is a bit. At odds,
  • Slot is used more often in Vue. React doesn’t need slot.

Each of these approaches can be logically reused, but each has some additional problems:

  • Mixin’s problem:

    • May depend on each other, mutual coupling, is not conducive to code maintenance;
    • Methods in different mixins may conflict with each other;
    • There are so many mixins that components can sense and even deal with them, which can snowball in code complexity
  • The problem with HOC:

    • You need to wrap or nest on top of the original components, and if you use HOC a lot, you get a lot of nesting, which makes debugging very difficult;
    • HOC can hijack props and can cause conflict if conventions are not followed
    • Props can also cause naming conflicts
    • wrapper hell

Have you ever seen a DOM structure like this?

This is what Wrapper Hell is all about

Therefore, the emergence of hook is epoch-making. It realizes the internal encapsulation of complex logic by means of function extraction. According to the above questions, some advantages of Hook are summarized:

  1. Reuse of logical code
  2. Reduced code size
  3. There is no trouble with this

With that in mind, let’s take a look at the react and Vue implementations:

The react hook profile

Dan’s video on hook is here. If you can’t watch it, you can try the introduction on the official website

React Hook {react Hook} React Hook {react Hook} React Hook {react Hook} React Hook {react Hook}

import React, { Component } from 'react';

export default class MyClassApp extends Component {
    constructor(props) {
        super(props);
        this.state = {
            x: 0.y: 0
        };
        this.handleUpdate = this.handleUpdate.bind(this);
    }
    componentDidMount() {
        document.addEventListener('mousemove'.this.handleUpdate);
    }
    componentDidUpdate() {
        const { x, y } = this.state;
        document.title = ` (${x}.${y}) `;
    }
    componentWillUnmount() {
        window.removeEventListener('mousemove'.this.handleUpdate);
    }
    handleUpdate(e) {
        this.setState({
            x: e.clientX,
            y: e.clientY
        });
    }
    render() {
        return (
            <div>
                current position x:{this.state.x}, y:{this.state.y}
            </div>); }}Copy the code

The online code demo is here

We use hook to realize the same logic

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

// Custom hook useMousePostion
const useMousePostion = (a)= > {
    // Initialize a state with hookuseState
    const [postion, setPostion] = useState({ x: 0.y: 0 });
    function handleMove(e) {
        setPostion({ x: e.clientX, y: e.clientY });
    }
    // Use useEffect to handle what the lifecycle can do in a class
    // Note: the effect is the same, but the actual principle is different. If you are interested, you can go to the official website for a detailed study
    useEffect((a)= > {
        // Handle componentDidMount and componentDidUpdate at the same time
        window.addEventListener('mousemove', handleMove);
        document.title = ` (${postion.x}.${postion.y}) `;
        return (a)= > {
            // Return function can be equivalent to executing something like componentWillUnmount when the component is unmounted
            window.removeEventListener('mousemove', handleMove);
        };
        // [] is a parameter that represents deps. React triggers this hook based on the deps passed in, internally implementing the objectIs
        // By default, no arguments are called every time render is performed. Giving an empty array causes each comparison to be the same and only executed once
    }, [postion]);
    // Postion can be returned directly, so as to achieve the reuse of logic ~, where the need to call it.
    return postion;
};

export default function App() {
    const { x, y } = useMousePostion(); // Internally maintain its own postion-related logic
    return (
        <div>
            current position x: {x}, y: {y}
        </div>
    );
}

Copy the code

The online code demo is here

React (object. Is) {react (objectobjectIs

It can be seen that after using hook, we put all the logic about position into a custom hook–useMousePostion, which is very convenient to reuse later. Moreover, we can maintain the unique logic of Postion internally without affecting the external content. Compared with the class component, Stronger abstraction ability.

Of course, react Hook is not so easy to use, and there are many articles explaining react Hook. This article is not too in-depth, but just a primer. Here are some good resources for you:

Introduction:

  • Official portal

Depth:

  • Dan himself wrote a good article about hook, strong Amway, deep into the internal implementation

Here are some of my own best practices for implementing Redux hooks. Note that I think so

Vue hook profile

A video of uVU’s presentation is here

Since VUe3.0 has not been released yet, let’s take a look at the demo code given by Utah:

import { value, computed, watch, onMounted } from 'vue'

function useMouse() {
  const x = value(0)
  const y = value(0)
  const update = e= > {
    x.value = e.pageX
    y.value = e.pageY
  }
  onMounted((a)= > {
    window.addEventListener('mousemove', update)
  })
  onUnmounted((a)= > {
    window.removeEventListener('mousemove', update)
  })
  return { x, y }
}

// Use this function in the component
const Component = {
  setup() {
    const { x, y } = useMouse()
    // Use with other functions
    const { z } = useOtherLogic()
    return { x, y, z }
  },
  template: `<div>{{ x }} {{ y }} {{ z }}</div>`
}
Copy the code

We can also separate some of the logic that needs to be reused into a single function called useMouse, and then some of the lifecycle and value contents defined in this function are “hooked” to the component when the setup function is called. And the data returned from this function can be used directly in the template, more specific gameplay we will wait for 3.0.

The basic content is not enough, after all, the actual API has not been released, if you want to know more about the specific content can see Utah’s explanation

same & diff Point

After looking at the implementation of two frameworks on hook, let’s do a simple comparison

  1. Same Point:
  • Both frameworks aim to solve some problems such as excessive reuse of logic and large code volume, including this problem. We seldom deal with this when using function function.
  • In a similar way, separate logic that can be reused is separated into a single function, which returns the data needed in the component, and internally maintains updates to the data, triggering updates to the view
  1. Diff Point:

React Hook is based on a linked list. It calls on the condition that every time a component is rendered, it executes all hooks sequentially, so this code will fail

function App(){
    const [name, setName] = useState('demo');
    if(condition){
        const [val, setVal] = useState(' '); }}Copy the code

Because the bottom layer is a linked list, the next of each hook points to the next hook. If will result in incorrect order, resulting in an error. Therefore, React is not allowed to use hook in this way.

Remember that vue hooks are only registered once when the Setup function is called. React data changes cause rerender, which re-registers hooks. React is much more difficult to use. The fundamental reason is that its response to data is proxy-based. In this scenario, function or template will be recalculated whenever data is changed, thus avoiding performance problems that react might encounter

React Has solutions to all of these problems. For example, useCallback, useMemo and other hooks can be introduced on the official website. Let’s take a look at the summary and comparison between Vue and React Hook.

1. More intuitive JavaScript overall;

2. The call sequence is not limited and can be called conditionally.

3. There will not be a large number of inline functions in subsequent updates, which will affect engine optimization or cause GC pressure;

4. You don’t always need to use useCallback to cache callbacks to child components to prevent overupdating;

5. You don’t need to worry about to send the wrong depend on the array to useEffect/useMemo useCallback leading to use outdated values in the callback – Vue rely on tracking is fully automatic.

It has to be said that vUE is better than React. Although vue borrowed react data, its natural responsiveness perfectly avoided some of the shortcomings encountered by React Hook

conclusion

  1. Function Component will be one of the development directions of various frameworks in the future. Function’s natural friendliness to TS is also an important influence.
  2. React Hook is more difficult to get started than VUE. Vue naturally avoids some difficult parts in React.
  3. Hooks are definitely a trend in the big front-end and are only just beginning: swiftu-hooks, Flutter_hooks…

Because the source code of VUe3.0 has not been released, there are a lot of implementation is guess, welcome to ask questions, discuss together!

If you feel useful, please give me a thumbs-up. Thank you, your thumbs-up is my continuous motivation ~