preface

This paper mainly records the more important knowledge points in Hook and the problems encountered in practical application, as well as some experience in referring to relevant documents

If there are mistakes in the article, please also see friends more advice, thanks in advance

The following left

I met

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

Although it is not necessary to understand the class component in the process of learning hooks, it is necessary to understand the class component first if you want to understand hooks quickly and easily, because most hooks are compared to the class component in the official website and other documents

As for why there is Hook, what problems it solves in our development, which is not within the scope of this paper’s record, interested friends can refer to here

basic

import React, { useState, useEffect } from 'react'; Function Example() {// Declare a state variable called "count". const [count, setCount] = useState(0); UseEffect (()=> {console.log(' loaded... ') return () => {console.log(' unbound... ') } }) return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }Copy the code

Above is a simple Hook, when we click the button, the number book on the page will increase, and the console will print out different information

Most intuitively, we no longer need to define a class class to useState to maintain the state of the component itself. Instead, we use useState to generate the state of the component and the methods that control it. Similarly, without the benefit of the component’s lifecycle, the methods we registered in useEffect are executed at first load and state update time

Here, use estate and useEffect are different hooks. You can do some of the things you do with class by calling different hooks in functions

Pay attention to the point

  • HookIs something that can be hooked into a function componentReact stateAnd life cycle, etc. Not in theclassUse in components
  • Can only be called from the outermost layer of a functionHook. Do not call in loops, conditional judgments, or subfunctions
  • Only in theReactFunction component or customHookIn the callHook
  • HookIs a way to reuse state logic, it does not reusestateItself,HookEach call to thestateIn short, a new onestate
  • HookUsing theJavaScriptClosure mechanism

Understanding these features of Hook will help us to become familiar with and use Hook

Why are sequential calls important to React Hook

Based on the hooks

useState

const [state, setState] = useState(initialState)Copy the code

Features:

  • useStateIs a function that returns an array (currentlystateAnd updatestateThe only argument is initialstate
  • During initial rendering, the state returned (state) is the same value as the first argument passed in
  • setStateFunction to updatestate. It receives a new onestateValue and queues a re-rendering of the component
  • initialStateWill only be used in the initial render, will be ignored later, if passed a function will only be called in the initial render, if null, the value of the variable will beundefined
Const [name, setName] = useState() name // undefined // setCount] =useState(()=> { const initialState = someExpensiveComputation(props); return initialState; })Copy the code
  • updatestateVariables always replace it instead of merging it,this.setstate()Will automatically merge
Const [state, setState] = useState({name: 'tadpole ', age: 18, hobby: 'Play game'}) // Use class this.setState ({age: 17}) // Use Hook setState(prevState => {return {... prevState, age: 17} })Copy the code
  • You can declare it multiple times

In addition, when declaring variables with useState, we can declare each variable individually, or we can use an object or array directly

Const [height, setHeight] = useState(10) const [width, setWidth] = useState(20) const [left, SetLeft] = useState(10) const [top, setTop] = useState(10) const [state, setTop] = useState({height: 10, width: 20, left: 10, top: 10 })Copy the code

In practice, it is a best practice to group states logically, avoiding the bloated state objects and maintaining the associated states in groups. For example, several of the variables declared above can be classified in this way

const [box, setBox] = useState({ height: 10, width: 20 }) const [position, setPosition] = useState({ left: 10, top: 10})Copy the code

useEffect

useEffect(() => {
    effect
    return () => {
        cleanup
    };
}, [input])Copy the code

Features:

  • By default, it is executed after the first rendering and after each update
  • Can put theuseEffect HookAs acomponentDidMount.componentDidUpdatecomponentWillUnmountThe combination of these three functions
UseEffect (() => {console.log(' method executed ') return () => {console.log(' unbound ')}})Copy the code
  • withcomponentDidMountcomponentDidUpdateDifferent, useuseEffectThe scheduling ofeffectIt does not block the browser from updating the screen, which means it is asynchronous
  • You can use multipleeffectUsed to separate different logic (e.g. for different purposes), meaning we can add more than oneeffect
  • The second parameter of effect can be configured to set the dependency and then execute the function when the dependency changes for performance optimization. If we only want the function to execute on the first load and unload, we can pass an empty array
// Only if count changes, UseEffect (() => {console.log(' method executed ') return () => {console.log(' unbound ')}}, UseEffect (() => {console.log(' method executed ') return () => {console.log(' unbound ')}}, [])Copy the code
  • All must be included in the dependencyeffectValues within the component used in
  • The cleanup function is executed before the component is unloaded. If the component is rendered multiple times (as it usually is), the previous effect is cleared before the next effect is executed
  • If you only want to run it on updateeffect, then you can use a mutablerefStore one manuallybooleanValue to judge
  • effectIt’s always in the render that defined itpropsstate

Recommended reading the full useEffect guide and how to send requests in Effect

useContext

const value = useContext(MyContext)Copy the code

If you’re not familiar with context, you can click here to see what context is

Features:

  • To receive acontextObject (React.createContext) and returns thecontextThe current value of the
  • useContextMust becontextThe object itself
  • The currentcontextValue from the upper component that is closest to the current component<MyContext.Provider>value propdecision
  • Call theuseContextComponents are always therecontextRerender when values change
Const themes = {light: {foreground: "#000000", background: "#eeeeee"}, dark: {foreground: "#eeeeee"} "#ffffff", background: "#222222" } } const ThemeContext = React.createContext(themes.light); function ThemedButton() { const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ) }Copy the code

Other Hook

useReducer

Alternatives to useState, understanding Reducer is easy if you are familiar with Redux

  • Receive a message of the form(state, action) => newStatereducerAnd returns the currentstateAnd what goes with itdispatchmethods
const initialState = {count: 0}; Function reducer(state, action) {switch (action.type) {case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'decrement'})}>-</button> <button onClick={() => dispatch({type: 'increment'})}>+</button> </> ); }Copy the code
  • reducerEssentially a pure function that returns one value at a time. That value can be a number, a string, an object, an array, or an object, but it’s always a value
  • ReactWill make suredispatchThe identity of the function is stable and does not change when the component is re-rendered
  • useReducerYou can also optimize performance for components that trigger deep updates because they can be passed to child componentsdispatchInstead of a callback function
  • reducerMore suitable for dealing with more complex thingsstateTo maintain the state of the component

The above example is a basic way to initialize state, but we can also choose lazy initialization

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

If you initialize this way, the value of state is init(initialArg)

useRef

const refContainer = useRef(initialValue)Copy the code
  • useRefReturns a mutablerefObject, its.currentProperty is initialized as the passed parameter (initialValue).
  • The returnedrefObjects remain constant throughout the life of the component, making it easy to store any mutable values
  • change.currentProperty does not cause the component to rerender
  • useRef()Create a normalJavascriptObject, and the same object is returned each time
Pay attention to the point

Before we get to useRef, it’s important to understand that for functional components, every state change retriggers render. In other words, the value we get when the component state changes is completely new, but React helps us remember the previous data

Using this feature of the REF object, we can implement:

  • For example, as mentioned earlier, it only runs on updateseffect
  • Gets the value of the previous roundpropsstate
  • Accessing child components becomes easy

useCallback

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

Each invocation of a function component executes all the internal logic and incurs a high performance cost, so useCallback is introduced to solve the performance problem. Where you need to use the cache function, this is where useCallback is used

The most common scenario is when a parent component passes a function to a child component, and useCallback is used to keep the child component from performing updates, provided that a dependency in the props does not change

Performance optimization is achieved by passing in an inline function and an array of dependencies as arguments to useCallback, a callback function that updates only when a dependency changes

  • Is executed when the component is first rendered and dependencies are updated
  • Returns a cached function
  • Do not perform operations inside this function that are not related to rendering, such as side effects
  • If the dependency array is not provided,useCallbackThis is done on every render; If it is an empty array, it will only be evaluated once on the first rendering

useMemo

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b])Copy the code

As with useCallback, it exists as a way to optimize performance. Unlike useCallback, useMemo returns a cached value

  • The cached values are recalculated during the first component rendering and dependency update
  • Returns a cached value
  • Do not perform operations inside this function that are not related to rendering, such as side effects
  • If the dependency array is not provided,useMemoThe new value is evaluated on each render, or only on the first render if it is an empty array

Customize the Hook

With custom hooks, component logic can be extracted into reusable functions

Before hooks, we used render props and higher-order functions to share state logic between components

Now we can use custom hooks to achieve the same functionality, but with much clearer logic

  • The customHookIs a function whose name isuseAt the beginning, other calls can be made inside the functionHook
  • No special identity is required. We are free to decide what its arguments are, and what should it return
  • The customHookIs a mechanism for reusing state logic without sharing data
function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  // ...

  return isOnline;
}Copy the code

Afterword.

The above mainly introduces some important features of Hook and hooks that are often used. Most of the content and examples of the article are from the official website. Then, it is the integration of knowledge points that I have sorted out and summarized

All examples for this article can be found here

Interested partners can click here, or scan the QR code below to follow my wechat public account, to view more front-end clips, welcome to star