Learn the basics of React. Learn the three properties of React. Learn the lifecycle of React

Hook profile

React Hook?

Hook is a new feature in React 16.8. It lets you use state and other React features without having to write a class.

React doesn’t use state in function components. If you’re not familiar with React, you can’t use state in functions. Hooks allow you to use state and other React features in function components.

As for the specific reason for the emergence of Hook, please refer to the official explanation: Motivation

A Hook is a function that allows you to “Hook” React state and lifecycle features into function components. Hooks cannot be used in class components. If you are fully familiar with hooks, you can write React applications using only function components.

In addition to the React built-in hooks, we can also use some third-party packaged hooks, or even our own packaged hooks.

Note that React 16.8.0 is the first version to support Hooks. The React use case version of this chapter is V17.0.2. If you want to test the effect, the React version needs to be greater than or equal to V16.8.0.

useState

UseState is a built-in React Hook that allows you to add a state Hook to the React function. UseState is a built-in React Hook that allows you to add a state Hook to the React function.

class Counter extends React.Component {
  state = {
    count: 0}; add =() = > {
    this.setState({ count: this.state.count + 1 });
  };
  render() {
    return (
      <div>
        <p>count: {this.state.count}</p>
        <button onClick={this.add}>+ 1</button>
      </div>); }}Copy the code

This simple piece of code completes a counter logic that would not work if written using a function component, which cannot use state. But now we can use the useState hook function to do the same thing in a function component, using the following example:

// The useState hook needs to be introduced
import React, { useState } from "react";

function Counter() {
  // declare count, the state variable
  const [count, setCount] = useState(0);

  function add() {
    setCount(count + 1);
  }
  return (
    <div>
      <p>count: {count}</p>
      <button onClick={add}>+ 1</button>
    </div>
  );
}
Copy the code

The above code uses useState to develop a counter function, which I find more elegant than the class approach. UseState uses the syntax:

const [xxx,setXxx] = useState(initValue)
Copy the code

The useState method takes the initial value of the state variable as an argument and returns an array of two elements, the first being the internal current state value and the second being the function that updates the state value. On the left side of the equals sign, we use array deconstruction to define the names of the two values. These two names are arbitrary, no special requirements, but generally take semantic names.

As shown in the above example, setCount is a method to update the state of count. It can be used in two ways: one is to directly pass in a new state value as a parameter, and the other is to pass in a function as a parameter. The parameter of the function is the old state value, and the return value is the new state value, as follows:

// setCount(count + 1);

setCount((count) = > count + 1);
Copy the code

If you define more than one state variable, just write one more line:

const [count, setCount] = useState(0);
const [name, setName] = useState('Tom');
Copy the code

useEffect

UseEffect is also a built-in Hook for React. It allows you to perform side effects on function components, such as ajax requests, when React renders or updates the Dom. Set up a subscription or start a timer or something. Normally these side effects are performed in a lifecycle hook, but there is no lifecycle in a function component, and useEffect emulates the lifecycle in a class component.

The useEffect hook is passed in as an argument to a function that performs the side effect operation. Again, in the counter example above, we introduce useEffect to perform the side effect operation of printing count. The code is as follows:

/ / into the hook
import React, { useEffect, useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);
  
  Use useEffect to print count
  useEffect(() = > {
      console.log(count);
  })

  function add() {
    setCount(count + 1);
  }
  return (
    <div>
      <p>count: {count}</p>
      <button onClick={add}>+ 1</button>
    </div>
  );
}
Copy the code

When the browser executes the code above, it prints 0 when the page is initialized and the status value of count is printed in real time when the count operation is performed. Recall that if we wanted to do this in a class component, we would print count in the life cycle componentDidMount and componentDidUpdate, respectively.

Thus, the useEffect has been simulated for two life cycles. One problem is that in the class component, I’m free to control the number of hooks in the lifecycle. If I don’t want to perform side effects on page updates, I remove componentDidUpdate and add it if necessary. UseEffect is used in both cycle phases by default. Is there any way to prevent the update phase from executing?

The answer is yes, useEffect can control the execution cycle, and I think this part is cleverly designed. If you don’t want to perform side effects during page updates, pass useEffect as a second argument, passing an empty array [] as follows:

useEffect(() = > {
    console.log(count); } []);// We pass the second argument, an empty array
Copy the code

When you refresh the browser, you will print 0 first, and when you count again, you will no longer print the updated value, that is, you will no longer perform the update phase. Isn’t that amazing, but at the same time a little weird, why pass an empty array? Smart kids should be able to think of something like, what happens if we pass a count variable into the array? When you put count in an array, the page updates will print again.

  useEffect(() = > {
    console.log(count);
  }, [count]); / / to the count
Copy the code

In fact, when the count changes, the update operation is performed again. This array is a bit like a listener in that when you pass an empty array, you don’t perform the update phase side effects, whereas when you pass in a specific variable, you only perform the update phase operations when the passed variable is updated. When the array is not passed by default, the side effects of the update phase are performed whenever there are any status updates.

There is another life cycle phase that is also important, and that is componentWillUnmount. Sometimes we need to remove things when a component is unmounted, most commonly the destroy timer.

UseEffect returns a function that is executed just before the component is destroyed. To demonstrate, I’ll rewrite the timer example above and apply the timer to change the counter to automatically increment by 1 per second and add the component destroy button:

import React, { useEffect, useState } from "react";
import ReactDom  from 'react-dom';

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() = > {
    // Update count with timer +1 per second
    setInterval(() = > setCount((count) = > count + 1), 1000); } []);// Define the component destruction method
  function onUnmount() {
    ReactDom.unmountComponentAtNode(document.getElementById("root"));
  }
  return (
    <div>
      <p>count: {count}</p>
      <button onClick={onUnmount}>The destruction</button>
    </div>
  );
}
Copy the code

The code in the example has been added to the timer, and the browser can increment the count by one every second. If you click the destroy button, you will see a warning from the browser

This is because the component was destroyed, but the timer program is still running, so we need to destroy the timer when the component is uninstalled. We can return a function in useEffect that destroys the timer as follows:

useEffect(() = > {
    // Save the timer to a variable
    const timer = setInterval(() = > setCount((count) = > count + 1), 1000);
    // Returns a function that is called before the component is unloaded
    return () = > {
        // Clean up timer
        clearInterval(timer)
    }
}, []);
Copy the code

So we’ve modeled the componentWillUnmount life cycle, isn’t that neat? To sum up, you can think of useEffect Hook as componentDidMount, componentDidUpdate and componentWillUnmount.

React not only has these two hooks, but also can refer to the Hook API index. The space here is limited, so I will not introduce one by one. By drawing inferences from one example, if I basically understand the above two hooks, I can understand other hooks.

Customize the Hook

Hook is js function in essence, we can completely customize the specific function of the Hook. A requirement for custom hooks is that the name must begin with use. We can use an existing Hook to repackage a new Hook. For example, we want to define a useMount Hook, which means that the Hook is only executed when the component is initialized.

import { useEffect } from "react";

const useMount = (fn) = > {
  useEffect(() = > {
    fn && fn()
  }, [])
}
Copy the code

Ha ha, a little too simple, but this package is a bit more semantic ah, it is a way of thinking. Since I don’t have a lot of practice myself, I won’t repeat it.

conclusion

So much for Hook. After all, I haven’t used React in my work and I can’t talk much about it. There are also a number of third-party hooks libraries that can be used. Here is a reference to the hooks library from Ali.

This is the last article in the React series to relearn React. It basically covers all the things to get started with React, except that there are only four articles in this article. It has to be said that React is much faster to learn than Vue, but if you want to use React well, there are still many details that need to be put into practice. I stopped writing about Redux because I’m lazy, my first nuggets article was about Redux and I don’t want to write about it anymore, and Redux isn’t a React app, it’s a non-mandatory tool, so I’ll read it later if I have to.

That’s it. Last entry of the year. I forgot it was Christmas, haha.

Please point out any mistakes.