2022 is coming, the front end development is very rapid, now the front end is no longer writing simple pages, with the Web big front end, engineering is becoming more and more hot, there are also many frameworks. Many companies are not only using a single framework, as the front end development of the two most popular frameworks in the country, are necessary to master. Therefore, I decided to learn React at the end of this year when the epidemic was raging, so as to gain more competitiveness in my future job search.

Learning stage, if there is something wrong, welcome to leave a message in the comment area, I timely correction

This article has been serialized, other chapters portal ⬇️

Chapter 1 – Understanding JSX syntax

Chapter 2 – Function components and Class components

Chapter 3 — Props and State

Chapter 4 – Event Handling

Chapter 5 -Ref and Refs

Chapter 6 – Life Cycle

Chapter 7 – Communicating Context across Components

React Hooks

Hook is a new feature in React 16.8. It provides functions with state and lifecycle features only available in class components. A Hook can only be used in a function component. A function component with a Hook is no longer stateless.

React is a function that allows you to “hook” React state and lifecycle features into a function component. React has some built-in hook functions. You can also customize your own hooks. Note that hook functions can only be called inside function components and cannot be nested within normal JS functions and if else and for loops. React identifies each hook according to the call order of hooks. If the call order is different, React will not know which hook it is

Note: class-related apis cannot be used in hooks, function components have no lifecycle hook functions, state and this do not exist…

useState

UseState Hook, provides state for function components, initializes data, and modifies data

import { useState } from 'react'
import ReactDom from 'react-dom'
function Demo() {
/** useState can accept an initial value of function type const [state, setState] = useState(() => {return 0}) */ 

  const [state, setstate] = useState(0)

  const handleClick = () = > {
    setstate(state + 1)}return (
    <div>
      <h1>{state}</h1>
      <button onClick={handleClick}>Click on the</button>
    </div>
  )
}
ReactDom.render(<Demo />.document.querySelector('#root'))
Copy the code

React imports useState and calls it in a function component that takes in an initial value argument, which can be any value. Returns an array, the first of which is the initial value passed in, and the second of which is a function we use to modify the data

When we call the second return value of the useState function to modify the component data, React will replace the old data with the new data and the component will be re-rendered. By clicking setState multiple times to modify the data, our useState will get the last data instead of reinitializing each render. However, it should be noted that we need to replace the old data with the new data instead of directly modifying the old data, otherwise the component will not update and re-render. For example, we change the code to:

.const [state, setstate] = useState({ name: 'ls'})...const handleClick = () = > {
    state.name = 'Ming'
    setstate(state)
  }
Copy the code

As you can see, no matter how much we click on it, it doesn’t work because the reference type is an address, and if we want to modify the data, we have to overwrite the old object with a new object, right

The useState argument can be written as an arrow function

const [state, setstate] = useState(() = > {
    console.log('useState')
    return {
      name: 'ls'}})Copy the code

useEffect

Effect Hook allows you to perform side effects in function components. Side effects mean manipulating DOM, fetching data, publishing and subscribing… Effect Hook (componentDidMount componentDidUpdate and componentWillUnmount

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

export default function Demo() {
  const [count, setCount] = useState(0)
  const handleClick = () = > {
    setCount(count + 1)
  }
  useEffect(() = > {
    document.title = 'You clicked${count}Time `
  })
  return (
    <div>
      <p>Click {count} times</p>
      <button style={{
        width: '70px', height: '30px', 
        backgroundColor: '#1E90FF', color: 'white',
        outline:'none', border: 'none',
        borderRadius: '5px'}}onClick={handleClick}
      >Click on the + 1</button>
    </div>
  )
}

ReactDOM.render(<Demo/>.document.querySelector('#root'))
Copy the code

As you can see, modifying the title of the document when clicked is an extra thing for the rendering component. This is a side effect code that needs to be written into useEffect

UseEffect dependencies

A dependency is a dependency that can set useEffect, and effect is executed only when count changes. For example, let’s modify the code:

const [money, setMoney] = useState(100)

const changeMoney = () = > {
    setMoney(
      money + 10)}return (
    <div>
      <h1>Count:{count}</h1>
      <h1>Money:{money}</h1>
      <button onClick={handleClick}>Modify the count</button>
      <button onClick={changeMoney}>Modify the Money</button>
    </div>
  )
Copy the code

As you can see, the first render is executed once, both when we click change Count and change Money. But when we click to modify Money, we don’t need to re-execute Effect because count hasn’t changed, so we need to add a dependency to Effect

useEffect(() = > {
    console.log('useEffect side effects performed ')
    document.title = 'Currently clicked${count}Time `
  },[count])
Copy the code

UseEffect receives the second parameter as an array, which contains the data that we effect depends on. If we click to change Money, we will no longer execute the effect function, thus skipping unnecessary execution

We can also set the dependency to an empty array so that the effect is only executed when the component is first rendered, which we can think of as the componentDidMount hook function

UseEffect Cleaning side effects

Cleanup side effects are operations that need to be cleared when a component is destroyed, such as unlistening events, timers, etc.

useEffect(() = > {
    const timer = setInterval(() = > {
      console.log('Timer is running')})return () = > { Window.clearInterval(timer) }
  })
Copy the code

UseEffect also implements the componentWillUnmount hook function by returning a function that is executed before each useEffect callback to clean up the effects of previous useEffect and component destruction

useContext

The useContext Hook can subscribe to the value of the context and read changes to the context, equivalent to static contextType = MyContext or < myContext.consumer > in the class component. This allows us to use context to share data in function components as well

import React, { useContext } from 'react'
import ReactDOM from 'react-dom'
const obj = {
  name: 'Ming'.age: 18
}
const userContext = React.createContext(obj)

function Son() {
  const user = useContext(userContext)
  return (
    <div>
      <p>Name: {user. The name}</p>
      <p>Age: {user. Age}</p>
    </div>)}function Person() {
  return (
    <div>
      <Son/>
    </div>)}function App() {
  return (
    <div>
      <userContext.Provider value={{name:'little red,age: 20}} >
        <Person/>
      </userContext.Provider>
    </div>
  )
}
ReactDOM.render(<App/>.document.querySelector('#root'))
Copy the code

To create three components and create a context to share data, we need to use useContext in the Son component to read the context closest to itself. This Hook is retriggered when the value of the nearest Provider changes. Components that invoke useContext always re-render the portal when the context value changes

Customize the Hook

In addition to the internal hooks that React gives us, we can also implement our own hooks. When we have a piece of logic that is used in multiple components, we can extract it into a single custom hook that can be introduced in the components we use instead of having to write each one

export default function Index() {
  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 (
    <div>
      <p>X: {position. X}</p>
      <p>Y: {position. Y}</p>
    </div>)}Copy the code

For example, if we have a piece of logic to get an axis that is needed in multiple components, we can extract this piece of logic into a single hook.js file

A new hook. Js

/ / the new hook. Js
import {useState, useEffect} from 'react'

export function useMove() {
  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 position
}
Copy the code

Add this hook to the component and modify the code:


import ReactDOM from 'react-dom'
import React from 'react'
import {useMove} from './hook'
export default function Index() {
  const { x, y } = useMove()
  return (
    <div>
      <p>X: {x}</p>
      <p>Y: {} y</p>
    </div>
  )
}

ReactDOM.render(<Index/>.document.querySelector('#root'))
Copy the code

In this way, we can introduce this hook in any component, but it is important to note that the custom hook name must be the same as the react internal hook with the small camel name