“This is the sixth day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

🧨 Hi, I’m Smooth, a sophomore SCAU front er

React Hook 🏆 will teach you how to use 11 React Hooks and learn how to use them.

🙌 if the article is wrong, please comment section correction, thank you!

What are React Hooks

React Hooks are new in React V16.8. They allow you to use state and other React features without having to write a class.

React Hooks are designed to strengthen function components so that you can write fully functional components without using “classes”.

Hooks are functions that allow you to “Hook” functions such as React state and lifecycle features into function components. Hooks cannot be used in class components — this allows you to use React without using class.

React Hooks features

  1. The code is clearer, and the class components are difficult to maintain and logic is not easy to reuse
  2. The state between hooks is separate and has its own context. There is no confusion of state between hooks
  3. Let the function have state management
  4. Avoid the side effects of repeated function execution (limited by relevant hooks)
  5. Hooks can reference other Hooks, which can be combined for easy reuse.
  6. It is easier to separate a component’s view from its state.




Conditions for using hooks

A Hook is essentially a JavaScript function, but there are two rules to follow when using it:

Use hooks only at the top level

Never call hooks in loops, conditions, or nested functions. Make sure you always call them at the top of your React function. By following this rule, you can ensure that hooks are called in the same order every time you render. This allows React to keep the hook state correct between multiple useState and useEffect calls.

Only the React function calls the Hook

Never call a Hook in a normal JavaScript function. You can:

  • ✅ calls the Hook in the React function component
  • ✅ calls other hooks in custom hooks

Follow this rule to ensure that the component’s state logic is clearly visible in your code.

In addition, React provides an eslint-plugin-react-hooks plugin to enforce these rules, warning you if you use them incorrectly

Use of React Hooks

Here we go!

1. useState

const [count, setCount] = useState(0)
Copy the code

Add an initial state (variable initialization) to the function Component, similar to this.setState in Class Component.

When we define the state variable with useState, it returns an array of two values. The first value is the current state, and the second value is the function that updates the state

Much like closures, it exposes the value inside the function and a function that modifies that value, except that the function updates the data asynchronously

Here is a simple demo that implements a counter

Requirement: Click on me to count + 1

As you can see, useState initializes count to 0 and provides a function called setCount that modifies the value of count. Each click of the button triggers an onClick event to call setCount, which adds +1 to count

The so-called batch update principle

Students familiar with React know that the so-called state changes follow the batch update principle inside React.

The so-called asynchronous batch means that if multiple state changes are involved in a page update, the results of multiple state changes will be merged to get the final result and then a page update will be carried out.

Why React Hook adopts the bulk update principle?

Official explanation: If not on the current screen, we can delay the execution of the relevant logic. If the data arrives faster than the frame rate, we can merge and batch update. We prioritized user interaction (such as animation of button clicks) and deferred less important background work (such as rendering new content just downloaded from the web) to avoid missing frames.

How do you identify asynchronous batch updates
  1. Where React can be controlled, it is asynchronous batch updates. Such as event functions, lifecycle functions, synchronization code within components.

  2. React allows you to synchronize batch updates. For example, setTimeout,setInterval, generated DOM events, including promises, are all synchronized batch updates.

React 18 uses createRoot to batch process external event handlers. In other words, the latest React setTimeout, setInterval and other things that cannot be controlled are changed to batch update.




2. useEffect

UseEffect (() => {// Write the code that executes after the component is mounted and after the component is re-rendered... Return () => {// Write the code to execute before the component is uninstalled... }}, [])Copy the code

UseEffect is called a side effect Hook, and this Hook is as basic as useState. Effect Hook allows you to perform side effects in function components, such as modifying data fetches, setting subscriptions, manually changing DOM, console.log(), Ajax operations in the React component, and so on. At the same time, you can use multiple effects to achieve separation of concerns.

Similar to computed properties in Vue

If you’re familiar with the React Class lifecycle functions, you can use the React class lifecycle functionuseEffectThe hooks ascomponentDidMount.componentDidUpdate 和 componentWillUnmountThe combination of these three functions.

UseEffect supports three parameters

  • The first argument is a function that represents the side effect function, which by default is executed after the first rendering and after every update.

  • The second argument is an array that specifies the dependencies of the first argument (the side effect function). The side effect function is executed only when the variables in the array change. If the array is empty, it means that the useEffect does not change with any variables, that is, it is rendered only once.

  • The third argument is the return value of useEffect, which returns a function. Before useEffect is executed, the returned function is executed, usually to add a destruction event

Matters needing attention

  1. UseEffect is executed after render, so the Hook can take a second argument to skip execution and will not execute after next render if the specified value has not changed.

  2. UseEffect when listening for a particular value, you cannot setValue it or it will go into an infinite loop until the page freezes.




3. useLayoutEffect

UseLayoutEffect is used in exactly the same way as useEffect. UseLayoutEffect differs in that it calls Effect synchronously after all DOM changes.

UseEffect: execute after render
UseLayoutEffect: executes after all DOM updates

You can use it to read DOM layouts and trigger rerenders synchronously. The update schedule inside useLayoutEffect is refreshed synchronously before the browser performs the drawing.

Of course, sometimes you may need to use another case, if you want to update the value (like ref), at this point you need to make sure it is up to date before any other code runs, at this point you can consider using useLayoutEffect instead of useEffect,

In general, if you want to reduce useEffect “page jitter” for layouts computed by JS, you can consider using useLayoutEffect instead.




4. useContext

Context provides a way to share such values between components without explicitly passing props layer by layer through the component tree.

Those familiar with React Context Api and Vue provide/ Inject Api will be familiar with the function of this hook.

If you don’t quite understand the function, see the following demo

On the root component we need to pass down a count attribute to the third level child component H

At this point, it would be a nightmare to pass layers through using the props method. And if we want to use count in component H but not in component B and E, we need to explicitly declare count in component B and E as well.

React provides the Context Api to deal with situations like this.

You can create a context object using React. CreateContext and distribute the count variable in the root component using the value property of context. Provider. Use useContext(Context) in the Function Component to get the corresponding value.

UseContext (MyContext) just lets you read the value of the context and subscribe to changes in the context. You still need to use < myContext. Provider> in the upper component tree to provide context for the lower component.

You can nest multiple context. providers if you want to pass multiple data to child components




5. useReducer

React Hook also provides a useReducer for state management, similar to Vue’s Vuex, a global state management tool

const [state, dispatch] = useReducer(reducer, initialArg, init);
Copy the code

The useReducer accepts three arguments

  • Reducer function
  • The initial value initialArg
  • (Optional) lazy-initialized init function, which accepts a function of the form(state, action) => newStateReducer, and return the current state and its matchingdispatchMethods.

This article will not cover the use of the third function (lazy init function), interested students can go to the official documentation for consumption.

The use of useReducer
  1. Create an initial repository of variablesinitialArgAnd managersreducer
  2. throughuseReducer(reducer, initialArg)In order to getstate 和 dispatch

Let’s go through a simple counter example to understand its basic usage:

The demo explain

  1. Start by creating the data warehouseinitialArgAnd set up a managerreducerExample
  2. throughuseReducerTo create a new demostate 和 dispatch
  3. Wrap the click eventdispatchEvent and pass the corresponding parameter
  4. managersreducerExampleAfter receiving the parameters, perform certain actions through the switch, such as changing state

throughdispatchTo go outactionFor example, type, payload

When to use useReducer and when to use useState?

UseReducer can be more useful than useState in some situations, such as when the state logic is complex and contains multiple subvalues, or when the next state depends on the previous state.

Deeply updated components for performance optimization

In the official documentation of useReducer, there is a sentence like this:

Using useReducer also provides performance optimization for components that trigger deep updates because you can pass dispatches to child components instead of callbacks.

In some cases we usually pass functions as props to the Child Component, so that every time the parent re-render, even if we don’t modify the function as props, the child component will re-render. Examples are as follows:

The parent component

Child components

Demo animation

Every time the parent component’s button is clicked, an effect is executed in the child component.

At this point, the callback we pass to the child component doesn’t change anything, and we naturally expect the Effect in the child component not to execute.

The mechanism for this is that React re-executes component functions each time it renders, and regenerates a callback function when the parent component is re-executed. Because React uses object. is internally, React considers that the props of the child component have changed.

The dispatch returned in useReduce is a function, but one of the advantages of useReducer is that dispatch does not reassign memory locations with re-render, For example, if we pass Dispatch as props to the Child Component, Effect in the child component will not be executed.

There is another way to solve this subcomponent function rerendering problem besides Dispatch, which can be found in the useCallback section below




6. useCallback

Let’s take a look at useCallback, which is best used for performance optimizations in React.

const memoizedCallback = useCallback(
  () => { doSomething(a) }, 
  [a]);
Copy the code

UseCallback accepts two arguments:

  • The first argument is a function that will only be regenerated if the corresponding dependency changes, or the function is “memorized.”
  • The second argument is an array representing the dependencies on which the first argument depends, and the function of the first argument is “erased” and regenerated only if one of the items in the array changes.

Most people who interact with React may be curious about how to use this Hook. Let’s recall the above example in the useReducer section.

We passed a callback function in the parent component as props to the child component. We didn’t change the callback in each render, but each time the parent re-render, React will still assume that callback changes resulting in redundant child re-render.

In this case, useCallback can be used to solve this example, as follows:

Change the parent component of the useReducer above to wrap the useCallback

You can see that we use useCallback to wrap the callback function passed to the child component, while the second dependency argument passes an empty array.

Show animation after change

If we click the button multiple times, the child component’s Effect will no longer execute.




7. useMemo

useMemo( () => fn, deps)
Copy the code

UseMemo is also a Hook for performance optimization, which allows any type of value to be remembered compared to useCallback. For this value, we are more likely to use function components, but we can use useMemo if we don’t want a function component rendering all the time (such as a function component that involves a lot of DOM manipulation) to incur additional performance costs, such as the renderExample component in the following example.

If useCallback was provided to developers by the React team as a way to optimize functions, then useMemo can be seen as a way to “memorize” values and thus optimize performance.

Again, it supports two arguments:

  • The first argument takes a function passed in, and the return value of the function call passed in is “remembered.” It is only when the dependency changes that the function passed in is re-evaluated for the new return.
  • The second argument is also an array that represents the dependencies corresponding to the first argument.

UseMemo (() => fn, deps) equivalent to useCallback(fn, deps)

Difference between useMemo and useCallback

  1. useMemoIt returns a value, not just a function
  2. useMemoThe cache is a value,useCallbackThe cache is a function

Convention. Now let’s look at this example

Every time we click on the Button component re-render, the value of the renderSubject will be recalculated, which means it will be printed each timeRerender!.

Let’s wrap renderExample in useMemo and tell React to “remember” the value of renderExample and try again

When we click the button on the page and the count changes to the re-render page, Because we use useMemo to pass in a function that returns data.map((item) =>

  • {item.name}
  • ) and the second argument is an empty array.

    No matter how re-render the page, the value returned in useMemo will not be recalculated as long as the dependency does not change.

    Now we’re going to change the dependency from an empty array to count again

    Not surprisingly, the renderExample value is rerendered as the count dependency changes

    About Performance Optimization

    UseCallback and useMemo are two hooks that React provides to developers as means of performance optimization.

    But most of the time, you don’t need to worry about optimizing unnecessary re-renders. React is very fast, and I can think of a lot of things you can do with your time that are much better than doing these kinds of optimizations.

    In the case of useCallback and useMemo, I personally believe that improper use of these hooks not only makes the code more complex, but also leads to performance degradation by calling the built-in hooks to prevent dependencies and Memoized values from being garbage collected.

    If there are cases where you can get the necessary performance gains from using these hooks, such as particularly complex interactive charts and animations, then these costs are worth bearing, but it’s best to measure them before using them.

    The official documentation states that there is no need to worry about creating functions that will cause performance problems. The examples we provide above are just to show you how they can be used, and their use is not recommended in real life scenarios.




    8. useRef

    const refContainer = useRef(initialValue);
    Copy the code

    Similar to useState, a variable is created and saved

    UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned persists throughout the life of the component.

    UseRef Hook has two main functions:

    • Get the Dom element. In the Function Component we can get the corresponding Dom element using the useRef.

    • A bond that guarantees a unique value between multiple renders.

    Let’s talk more about the second point

    UseRef keeps a unique reference to the returned value in all render. Because all assignments and values to ref are the final state, there is no different isolation in different render.

    • UseRef creates a variable and saves it without reinitializing the value for component re-rendering (unlike useState)

    • Reassigning ref.current does not trigger component rerendering

    Remember that when the ref object’s contents change,useRef 并Don’tLet you know. change.currentProperty does not cause the component to rerender. This is required if you want to run some code when React binds or unbinds a DOM node’s REFThe callback refTo implement.

    Same old rule. Let’s do an example

    Based on the useMemo example, a new useRef is added, which continuously assigns values to ref.current until count equals 5, then clearInterval clears, and console.log() is used to see the changes

    The demo process

    As you can see, as expected, useRef creates variables that are constantly reassigned to ref.current, and the component is not rerendered, but is slowly changing according to the rules.




    9. useImperativeHandle

    useImperativeHandle(ref, createHandle, [deps])
    Copy the code

    UseImperativeHandle is a Hook that many students may not use very much in daily life, but in some cases, it can help us achieve some unintended effects.

    • Ref represents the ref object that needs to be assigned.
    • CreateHandle returns the value of ref. Current.
    • Deps depends on arrays, and createHandle is re-executed when the dependency changes.

    useImperativeHandleYou can use it againrefTo customize the instance value exposed to the parent component. In most cases, imperative code like ref should be avoided.useImperativeHandleShould be withforwardRefUsed together

    demo

    In this case, the parent component rendering
    can call inputref.current.focus ().




    10. useDebugValue

    useDebugValue(value , fn)
    Copy the code

    UseDebugValue can be used to display the tag of a custom hook in the React developer tool. It takes two arguments:

    • Value is the variable we will focus on and represents the hook flag displayed in DevTools.
    • Fn indicates how to format the variable value, which is called only when the Hook is checked. It takes a debug value as an argument and returns a formatted display value.

    For example, a custom Hook that returns a Date value can avoid unnecessary toDateString calls by formatting functions:

    useDebugValue(date, date => date.toDateString());
    Copy the code

    When we customize some hooks, we can use the useDebugValue and React DevTools to quickly locate our user-defined hooks.

    case

    React DevTools uses useDebug to define hello React Components.

    One thing to note
    • UseDebugValue should be used in custom hooks; it is not valid if used directly within components.

    • Most of the time you don’t need to use this Hook, unless you explicitly flag the Hook when writing some common library hooks.




    11. Custom hooks

    A custom Hook is a function whose name starts with “use” that can call other hooks from within.

    More easily understood, custom Hook is to extract and integrate the business logic we need together (component extraction), similar to Vue3 Composition API, one custom Hook can be understood as setup(), We simply extract some common code between the two functions into a separate function. Custom hooks are a convention that naturally follows Hook design, not a Feature of React.

    How to customize Hook
    1. Customize a hook function
    2. Write the business logic you need inside the Hook function (such as introducing other hooks, etc.)
    3. The return value is an array in which the first value is a variable and the second value is the function that modifies that variable
    4. Export custom hook functions
    5. Introduce the custom Hook where it is needed

    For example, useName and useFriendStatus in # 10 above are custom hooks

    Unlike the React component, custom hooks do not need to have a special identity. We are free to decide what its arguments are and what it should return (if necessary). In other words, it’s just like a normal function. But its name should always start with use, so it can be seen at a glance that it meets Hook rules.


    🎁 thank you for reading this article, I hope you can help, if you have any questions welcome to point out.

    🎁 I’m Smoothzjc, please like it if you think it’s all right ❤

    🎁 I will also work hard to produce more good articles in the future.

    🎁 interested partners can also pay attention to my public account: Smooth front-end growth record, public account synchronous update

    Writing is not easy, thanks for your support ❤

    Phase to recommend

    A rare Webpack learning guide (9K words to get you started with Webpack and master the common advanced configuration)

    Github + Hexo Implement your own personal blog, Configuration theme (super detailed)

    10 minutes to thoroughly Understand how to configure subdomains to deploy multiple projects

    This article explains how to configure pseudo static to solve the 404 problem of deployment project refresh page

    Learn common horizontal and vertical Centered interview questions in 3 minutes

    React: Emoji input with Antd+EMOJIALL

    【 Suggested collection 】 a summary of git common instructions!! Suitable for small white and want to understand the basic instructions of Git at work.

    A brief introduction to javascript prototypes and prototype chains