What are Hooks?

-Blair: That’s what I learned from the Hooks. Functions that allow you to “hook” React state and lifecycle features into function components. React 16.8 is a new feature. It lets you use state and other React features without having to write a class.

What it does: Provides functions to function components, such as state and life cycles, that are originally provided in Class components

  • Hooks can only be used in function components
  • Can be understood as hooking the class component’s features for the function component via Hooks

Comparison of component development patterns before and after Hooks

  • React V16.8 before: Class component (provides state) + function component (displays content)

  • React V16.8 and later:

    1. Class component (provides state) + function component (presents content)
    2. Hooks(provide state) + function components (display content)
    3. Mix these two approaches: use class components for some functions, Hooks+ function components for some functions

Why Hooks

Two perspectives: 1 component state logic reuse 2 class component itself problems

The essence of the React component

React is a JavaScript library for building user interfaces.

The React component encapsulates specific functions and is mainly used to split the UI.

The React component Model is a straightforward mapping from Model to View. The Model corresponds to the React function as state and props

Formula: Component (State+Props) = UI

Problems with the class component itself

The class component does not perform its most important function in rendering the UI by state:

  • Components rarely inherit from one another
  • Components rarely visit each other

Benefits of functional components

  1. The function itself is simpler and better able to render the UI based on state
  2. Hooks give function components the ability to maintain state internally
  3. Hooks bring logical reuse capabilities to components

Use policy for hooks

strategy

  1. React has no plans to remove classes from React

  2. Hooks and existing code work together, and you can use them incrementally:

    1. Large-scale refactoring of existing components directly using Hooks is not recommended
    2. Hooks are recommended for new functions. If complex functions cannot be implemented, use class
    3. Find a simple, non-core component and start using hooks
  3. Class component-related apis are not used in hooks

    1. The state and setState
    2. Hook function,componentDidMount,componentDidUpdate,componentWillUnmount
    3. `thisRelated usage
  4. The original learning content is still to use

    1. JSX:{},onClick={handleClick}, conditional rendering, list rendering, style processing, etc
    2. Component: function component, component communication
    3. React development concept:Unidirectional data flow,State of ascension

UseState – Basic use – Learn the first hooks

You can use useState to provide state for function components

Usage scenarios

Use the useState Hook when you want to use component state in a functional component

role

Provide state for function components

steps

  1. Import the useState function

  2. Call the useState function, passing in the initial value, returning the state, and a function to modify the state

  3. use

    1. Displayed in JSXstate
    2. Call the function that modifies the state at a specific time to change the state

You look at

import { useState } from 'react'
// useState is a hook, hook is a function starting with use
const Count = () = > {  
  // 0 is the initial value
  The return value is an array
  const stateArray = useState(0)

  // Status value -> 0
  const state = stateArray[0]
  // A function to modify the state
  const setState = stateArray[1]

  return (
    <div>{/* Display status values */}<h1>useState Hook -> {state}</h1>{/* Click the button to make the status value +1 */}<button onClick={()= > setState(state + 1)}>+1</button>
    </div>)}Copy the code
  • Parameter: initial status value. For example, passing a 0 indicates that the initial value of the state is 0

    • Note: The state here can be any value (for example, value, string, etc.), and the state in the class component must be an object
  • Return value: array, containing two values: 1 state value (state) 2 Function to modify the state (setState)

Use array deconstruction to simplify code

Use array deconstruction to simplify useState. Convention: The name of the function that changes the state begins with set, followed by the name of the state

// The name can be any name

const [state, setState] = useState(0)
const [age, setAge] = useState(0)
const [count, setCount] = useState(0)
Copy the code

UseState – Handles form elements

  1. Use useState to initialize content and modify content methods
  2. Set the value and onChange attributes to the input element

The ground sample

import React, { useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
  const [content, setContent] = useState(' ')
  return (
    <div>
      {content}
      <input value={content} onChange={(e)= > setContent(e.target.value)} />
    </div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code

UseState callback function format

UseState two formats

Format 1: Pass the value

useState(0) useState('abc')

Format 2: Incoming callback

UseState (() => {return initial value})

  1. The return value of the callback function is the current value of the state
  2. The callback function fires only once

Usage scenarios

Format 1: Pass the value

If the state is just plain data (for example, string, number, array, etc.) you can use useState directly (plain data)

Format 2: Incoming callback

  1. The initial state takes some calculation.UseState (()=>{here is some calculation, return result}))

SetXXX can be a callback

States need to be accumulated iteratively. SetXXXXX ((last value) => {return new value})

Example – Classic scenario

We want the state to have the effect of continuous superposition

import React, { useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
  const [count, setCount] = useState(0)
  const hClick1 = () = > {
    setCount(count+1)
    setCount(count+1)
    setCount(count+1)}const hClick2 = () = > {
   setCount((count) = >count+1)
   setCount((count) = >count+1)
   setCount((count) = >count+1)}return (
    <div>
      count:{count}
      <button onClick={hClick1}>Multiple consecutive setCount- values</button>
      <button onClick={hClick2}>Multiple consecutive setCount- values</button>
    </div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))

Copy the code

summary

  1. Parameters for useState come in two formats

    1. valueconst [count, setCount] = useState(0)
    2. The callback functionConst [count, setCount] = useState(()=>{return initial value})
  2. Arguments to setXXX have two formats, where functions can be used to superimpose state

setCount(100)

setCount(initState= > { 
  // ...
  return newState
})
Copy the code

demo

// Countdown demo
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
export default function App () {
  const [count, setCount] = useState(10)
  console.log(count, setCount)
  const hClick = () = > {
    console.log(11)
    const time = setInterval(() = > {
      setCount((count) = > {
        if (count === 1) {
          clearInterval(time)
        }
        return count - 1})},1000)}return (
    <div>
      <p>The countdown</p>
      <h1>{count}</h1>
      <button onClick={hClick}>The countdown</button>
    </div>
  )
}
ReactDOM.render(<App />.document.getElementById('root'))

Copy the code

UseState – Component update process

background

Function components have no life cycle

The update process

The sample code

import { useState } from 'react'

const Count = () = > {  
  console.log('Count... ')
  const [count, setCount] = useState(0)
  return (
    <div>{/* Display status values */}<h1>useState Hook -> {count}</h1>{/* Click the button to make the status value +1 */}<button onClick={()= > setCount(count + 1)}>+1</button>
    </div>)}Copy the code

The update process

Use useState Hook to execute the function component and change the state value:

  • Component first render:

    1. Execute the code logic in the function
    2. calluseState(0)Take the parameter passed as the initial value of the state, which is: 0
    3. Render component, at this point, the acquired state count value is: 0

The user clicks the button and calls setCount(count + 1) to change the state. As the state changes, the component is re-rendered

  • Component second render:

    1. Execute the code logic in this component again

    2. Call useState(0) again:

      1. React gets the latest state value instead of the initial value
      2. The latest status value in this case is 1
    3. Render the component again, at which point the obtained state count value is: 1

The initial value (parameter) of useState only takes effect when the component is first rendered

const [count, setCount] = useState(() = >{
  console.log('useState... ') // This sentence will be output only once
  return 0
})
Copy the code

That is, useState gets the latest state value for each subsequent render. The React component remembers the latest state value each time!

summary

Status updates, where the logic of the entire component is run again;

UseState only uses the initial value of the state for the first rendering of the component, and then the latest value of the state

The useState Hook is used to manage state, which enables function components to maintain state. That is, the state is shared between multiple renders of a function component.

How do I provide multiple states for function components?

Two kinds of schemes

  • Plan 1:UseState ({state 1, state 2..... })
  • Scheme 2:UseState (State 1) useState(State 2)

Scheme 2 is recommended

You can call useState Hook several times, and each time you call useState Hook you can provide one state.

Note:

Hooks: setXXX(new value) ==> Replace previous value with new value

Class: setState({attribute to modify})

Rules for using useState

The rules

  1. UseState can only appear directly inside a function component

  2. UseState cannot be nested in if/for/

    Reason: React identifies each Hook according to the sequence in which Hooks are called. If the sequence is different, React cannot know which Hook it is. You can view it through the developer tools

UseEffect – Understand side effects

Functional components:

  • Render UI based on data (state/props)
  • Side effects: Data (Ajax) requests, manual DOM modification, start timer, empty timer, add event listener, delete event, localStorage operation, etc

conclusion

For the React component, anything other than rendering the UI is a side effect.

UseEffect – Basic use

Using the step

1. Import useEffect
import { useEffect } from 'react'

// 2. Use useEffect
useEffect(() = > {
	console.log('useEffect 1 executed, can do side effects')
})
useEffect(() = > {
	console.log('useEffect 2 executed, can do side effects')})Copy the code

Execution time

After the render job is done, Effect is executed;

If multiple definitions are specified, they are executed in sequence.

case

import React, { useState, useEffect } from 'react'
import ReactDom from 'react-dom'
export default function App () {
  useEffect(() = > {
    console.log('useEffect')
    document.title = 'count' + count
  })
  const [count, setCount] = useState(0)
  return (
    <div
      onClick={()= >{setCount(count + 1)}}> Function component {count}</div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code

UseEffect – Sets dependencies

UseEffect dependencies

UseEffect takes two parameters:

Parameter 1: Side effect function.

Parameter 2: The dependency to execute the side effect function: It determines when to execute parameter 1 (side effect function)

UseEffect complete format

Case 1: No second argument. Timing: Execute after each update

Case 2: Takes a second argument, which is an empty array. Execution time: This parameter is executed for the first time

useEffect(() = > {
  // The contents of the side effect function
}, [])
Copy the code

Usage scenario: 1 Event binding 2 Sending a request to obtain data.

Case 3: Takes a second argument (array format) and specifies a dependency. Execution time :(1) execute once initially. (2) execute once if the value of the dependency changes

useEffect(() = > {
  // The contents of the side effect function}, [dependencies1, the dependencies2. ] )Copy the code

The dependency here is the state defined in the component.

Reference:

  1. UseEffect Complete Guide: Overreacted. IO/zh-Hans/A-C…

UseEffect Sends a request

format

// Use it correctly
useEffect(() = > {
  // Define a function
  async function fetchMyAPI() {
    let url = 'http://something/' + productId
    let config = {}
    const response = await myFetch(url)
  }
  / / invoke it
  fetchMyAPI()
}, [productId])
Copy the code

Note: Effect can only be a synchronous function, not async

// Error:

// Do not add async to useEffect
useEffect(async() = > {const res = awiat xxx()
    return () = >{}}, [])Copy the code

UseEffect – The return value of the side effects function – clears side effects

The return value of the side effect function

format

useEffect(() = > {
  // The contents of the side effect function

  returnReturn value of the side effect function}, [])Copy the code

The return value of the side effect function is optional and can be omitted. You can also return a cleanup function to clean up side effects

useEffect(() = > {
  // The contents of the side effect function

  return() = > {/* Do the cleanup */ } // Clean up the function
}, [])
Copy the code

The execution timing of the cleanup function:

  • The cleanup function is executed when the component is unloaded and before the next side effect function call

Example: Execution timing

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

function Com1 () {
  useEffect(() = > {
    console.log('Child component side effect function')
    
    return () = >{
      console.log('Cleanup function for child component side effect function')}}, [])return <div>Child components</div>
}
export default function App () {
  const [isShow, setIsShow] = useState(true)
  const [count, setCcount] = useState(0)
  
  useEffect(() = > {
    console.log('Contents of the parent component's side effect function')

    return () = > {
      
      console.log('Contents of cleanup function for parent component side function')
    }
  }, [count])
  
  return (
    <div>
      {isShow && <Com1 />}
      <button onClick={()= >setIsShow(! IsShow)} > delete | create child component</button>
		<button onClick={()= >SetCcount (count+1)}> Click +1, {count}</button>
    </div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code

Example – Simulate componentWillUnmount

useEffect(() = >{
  return () = >{
    // Do the cleanup}}, [])Copy the code

summary

Case 1: No second argument. Execution timing: Initial execution, after each update.

Analog componentDidmount + componentDidUpdate

useEffect(() = > {
  // The contents of the side effect function
})
Copy the code

Case 2: Takes a second argument, which is an empty array. Execution time: This parameter is executed for the first time.

Simulation componentDidMount

useEffect(() = > {
  // The contents of the side effect function
}, [])
Copy the code

Usage scenario: 1 Event binding 2 Sending a request to obtain data.

Case 3: Takes a second argument (array format) and specifies a dependency. Execution time :(1) execute once initially. (2) execute once if the value of the dependency changes

useEffect(() = > {
  // The contents of the side effect function}, [dependencies1, the dependencies2. ] )Copy the code

The dependency here is the state defined in the component.

Case 4: The dependency is empty, there is no specific side effect function, and there is a cleanup function for the side effect function

Simulation: componentWillUnMount

useEffect(() = > {
  
  return () = > {
  	// Side effects function cleanup function, simulated componentWillUnMount}}, [])Copy the code

Custom hooks

define

In addition to using the built-in Hooks, you can also create your own Hooks.

Custom Hooks reuse different state logic for different components.

  • Custom Hooks is a function to define the function name must begin with the use, through the function name is the React to use to judge whether Hooks
  • Hooks can only be used in function components or other custom Hooks; otherwise, an error is reported!
  • Custom Hooks extract component state logic, with different parameters and return values for different functions (as with normal functions)

Usage scenarios

Reuse the component state logic by extracting it into reusable functions (custom Hooks).

Be born code

// museMouse.js
import { useEffect, useState } from 'react'
export default function useMouse() {
  // Logical processing
  const [position, setPosition] = useState({
    x: 0.y: 0,
  })

  useEffect(() = > {
    const move = (e) = > {
      setPosition({
        x: e.pageX,
        y: e.pageY,
      })
    }
    document.addEventListener('mousemove', move)
    return () = > {
      document.removeEventListener('mousemove', move)
    }
  }, [])
  
  // Return status
  return position
}
Copy the code

UseRef – DOM operation

content

Use scenario: Obtain the DOM when performing DOM operations on the React

Function: Returns a mutable object with the current property through which DOM manipulation can be performed.

const inputRef = useRef(null)
Copy the code

Explanation:

  • Parameters: When retrieving the DOM, it is generally set to NULL
  • Return value: the object containing the current property.
  • Note: Whenever you operate on the DOM in React, you can use the useRef Hook to retrieve the DOM (e.g., the width and height of the DOM).
  • Note that useRef can be used to manipulate components as well as the DOM

Core code:

// 1. Import useRef
import React, { useRef } from 'react'
import ReactDom from 'react-dom'

class Com1 extends React.Component {
  state = {
    a: 100
  }

  render () {
    return <div>com1, {this.state.a}</div>}}export default function App () {
  // 2. Call useRef(initial value) to get the reference object
  // 3. Set the reference object to any component/element
  // 4. Get the component/element by referring to the object.current
  const refTxt = useRef(null)
  const refCom1 = useRef(null)
  console.log(refTxt)

  const click = () = > {
    console.log(refTxt, refCom1)
    console.log(refCom1.current.state.a)
    // console.log(refTxt.current.value)
    // refTxt.current.style.backgroundColor = 'red'
  }
  return (
    <div>
      useRef, <input ref={refTxt} />{'}<button onClick={click}>Click to get the value in the input</button>
      <br />
      <Com1 ref={refCom1} />
    </div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code

UseRef – Share data between multiple renders

The function component, while intuitive and simplifying the logic of thinking about UI implementation, lacks an important capability compared to the Class component: the ability to share data between multiple renders.

The problem to import

import React, { useEffect, useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
  const [count, setCount] = useState(0)
  let timeId = null
  console.log(timeId)
  useEffect(() = > {
    timeId = setInterval(() = > {
      setCount((count) = > count + 1)},1000)
    console.log(timeId)
  }, [])

  const hClick = () = > {
    console.log(timeId)
    clearInterval(timeId)
  }

  return (
    <div>
      count:{count}
      <button onClick={hClick}>Click stop timer</button>
    </div>
  )
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code

Analysis of the

SetCount causes the component to be re-rendered, and when re-rendered, the following code is repeated

let timeId = null
Copy the code

Therefore, you cannot save timeId

Train of thought

Save the timeId in a location that won’t be lost for multiple renders.

steps

// 1. Import useRef
import React, { useRef } from 'react'Components () {// 2. Call useRef,
  const timeRef = useRef(null)
  // 3. Store data to referenced currentTimeref. current = Data you need to share between multiple renders}Copy the code

UseContext – Global status

UseContext steps

A total of 3 steps:

  1. Import and call the createContext method to get the Context object and export
import { createContext } from 'react'
export const Context = createContext()
Copy the code
  1. Wrap the root component with the Provider component and provide the data to be shared through the value property
return (
  <Context.Provider value={Put the data to be passed here}>< root component contents />
  </Provider>
)
Copy the code
  1. In any descendant component, if you want to get public data:

Import useContext; Call useContext(the context exported in the first step) to get the value of value

import React, { useContext } from 'react'
import { Context } from './index'
constFunction component =() = > {
    constPublic data = useContext(Context)return(Contents of function components)}Copy the code

Bao, you see this will not give me a star?

PS: If there are any mistakes in the content, please point them out (feel uncomfortable to make fun of them); If there is help, welcome to like and collect, please reprint the source, if there is a problem also welcome private communication