The React Hooks are the hottest new feature in the React ecosystem. It changes the way the React class was developed to a functional form. It changes the complex form of state manipulation and makes it easier for programmers to use. It changes the reusability of a state component, making it much more reusable. If you are a React fan or are working on React development projects, you can take an hour to read this article (video). You are sure to learn something and become fluent in using React Hooks in your work. Which is to be fixed by Hooks. I think that after you learn and use Hooks, you will overthrow your current React development style and love it.

Conscientiously share technology and strive to achieve the goal of 1000 free videos. [359] has been recorded. Keep it up.

P00:React Hooks video list

Here ARE the links to watch all the videos (and the corresponding text version of the tutorial below) :

  • P01:React Hooks introduction and environment setup
  • P02: Introduction to useState and multi-state declarations
  • P03:useEffect replaces commonly used life cycle functions
  • P04:useEffect implements componentWillUnmount life cycle function
  • P05:useContext makes it easier for parent and child components to pass values
  • P06: Introduction and simple use of useReducer
  • P07:useReducer instead of Redux small case -1
  • P08:useReducer instead of Redux small case -2
  • P09:useMemo optimizes React Hooks program performance
  • P10:useRef retrieves DOM elements and saves variables
  • P11: Custom Hooks function to get window size

P01:React Hooks introduction and environment setup

My ability is limited, although the article has been careful to correct, but inevitably some mistakes, please correct.

Course is an introduction to

This course is completely free and includes both text and video versions. The correct learning sequence is to watch the video first and then practice or review the text version, which can save you a lot of time.

Learn how to React before you learn how to React.

1.React16 Free Video Tutorial (28 episodes)

2.Redux Free Video Tutorials (24 episodes)

React Router (9 episodes)

If you have any problems in learning, you can join the ReactQQ group 159579268. There are already more than 1000 people studying and discussing with me.

Introduction of the React Hooks

Since FaceBook’s React team released Hooks in late 2018, React developers have been rave about them. React Hooks replace inherited classes with functions and use prefunctions to manage state. Use the Hooks to define components that do not use classes. Components are divided into stateful components and stateless components. Stateful components are declared as classes, while stateless components are declared as functions. Now all components can be declared as functions.

Remember that I learned from you in a few lessons. Remember that react-hooks are good for me.

Create a project using create-react-app

Create-react-app has been used many times in videos. It is the official react scaffolding, so it has the best stability and usage. You can use it with no fear.

Here I create a new folder for ReactHooksDemo on drive D, and create a demo01 project using create-react-app in the folder. All of our actions take place at the command prompt (terminal as I like to call it).

D: // Go to drive D mkdir ReactHooksDemocd ReactHooksDemo
create-react-app demo01
Copy the code

This process depends on your network situation, the time in my company is about 30 seconds, about 15 minutes at home, I do not know why, can only be said to be the network difference. Once set up, I minimize the project (delete most of the code and files under/SRC).

Leave only the/SRC /index.js file and cut the code inside to look like this:

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<App />, document.getElementById('root'));
Copy the code

Now that the development environment is set up, let’s compare the original script to the one that now has React Hooks.

React Hooks

Let’s start with the simplest form of a striated component, where when we click a button, the number of clicks increases.

Originally written:

import React, { Component } from 'react';

class Example extends Component {
    constructor(props) {
        super(props);
        this.state = { count:0 }
    }
    render() { 
        return (
            <div>
                <p>You clicked {this.state.count} times</p>
                <button onClick={this.addCount.bind(this)}>Chlick me</button>
            </div>
        );
    }
    addCount(){
        this.setState({count:this.state.count+1}}})export default Example;
Copy the code

React Hooks

import React, { useState } from 'react';
function Example(){
    const [ count , setCount ] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()= >{setCount(count+1)}}>click me</button>
        </div>)}export default Example;
Copy the code

From this comparison you can see that Hooks are essentially a special class of functions that can inject special functions into your function component. This sounds a bit like old React Mixins. Which is the purpose of which is to get you to stop writing class and to get function to rule.

P02: Introduction to useState and multi-state declarations

I started using useState in the last class, but I didn’t explain it in detail, just in passing. This lesson will take a closer look at the useState API. You can review the use of useState by opening the code from last lesson.

The introduction of useState

UseState is a react hook function that declares state variables.

UseState is used in three ways: declare, read, and modify. Master these three aspects, and you’ll basically be using useState.

Let’s take a look at the declaration. The code from the previous lesson is as follows:

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

This approach is ES6 syntax for array deconstruction, so that the code looks easy to understand. ES6 grammar has been used frequently at work, so if you are not familiar with ES6 grammar, I think it is necessary to spend 2 days to learn. Instead of array deconstruction, the syntax above would be written as the following three lines:

let _useState = userState(0)
let count = _useState[0]
let setCount = _useState[1]
Copy the code

The useState function takes the Initial state and returns an array with bit 0 of the current state and bit 1 of the method function that can change the state. So this code declares a state variable count, sets its initial value to 0, and provides a method function that changes the state of count.

Now that you have declared a state, let’s look at how to read the value in the state.

<p>You clicked {count} times</p>
Copy the code

As you can see, it’s very easy for us to read. Just use {count}, because count is a variable in JS. If you want to use JSX, add {} to the value.

Finally, to see how to change the value in State, look at the following code:

<button onClick={()=>{setCount(count+1)}}>click me</button>
Copy the code

Call the setCount function directly, which accepts the modified new state value as an argument. React is left to re-render the components. React automatically helps us remember the last state value of the component, but this memory also causes us a little trouble, but this trouble you can think of as a rule, as long as the rules are followed, we can happily code.

Precautions for multi-state declarations

For example, we now declare multiple states, such as age, sex, and work. I could write the code like this.

import React, { useState } from 'react';
function Example2(){
    const [ age , setAge ] = useState(18)
    const [ sex , setSex ] = useState('male')
    const [ work , setWork ] = useState('Front-end Programmer')
    return (
        <div>
            <p>JSPang is {age} years old</p>
            <p>Gender: {sex}</p>
            <p>Work is: {5}</p>
            
        </div>)}export default Example2;

Copy the code

When using useState, only the initial value is assigned and no key is bound. How does React ensure that the three USEstates find their corresponding states?

React is determined by the order in which useState appears

For example, let’s change the code to look like this:

import React, { useState } from 'react';

let showSex = true
function Example2(){
    const [ age , setAge ] = useState(18)
    if(showSex){
        const [ sex , setSex ] = useState('male')
        showSex=false
    }
   
    const [ work , setWork ] = useState('Front-end Programmer')
    return (
        <div>
            <p>JSPang is {age} years old</p>
            <p>Gender: {sex}</p>
            <p>Work is: {5}</p>
            
        </div>)}export default Example2;

Copy the code

The console will give us an error as follows:

 React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render 
Copy the code

UseState cannot be used in if… else… Calls to such conditional statements must be rendered in the same order. If you still don’t understand, remember that React Hooks cannot appear in conditional statements because they must have exactly the same render order.

In this lesson, we will explain the useState function API in detail. We’ll continue next time.

P03:useEffect replaces commonly used life cycle functions

When making components with Class, you often use lifecycle functions to handle extra things (side effects: actions performed at specific times or events, such as Ajax requests for back-end data, adding login listeners and cancelling logins, manually modifying the DOM, and so on). A similar lifecycle function is needed in React Hooks, such as useEffect, which executes on every State update. Let’s start with the useEffect function. It is like a wild horse, and when you do not tame it, it feels difficult to live with and even impossible to master; But when you tame it, you will find it gentle and lovely, so you can’t put it down.

withClassAdds a life cycle function to the counter

To give you a better understanding of useEffect, add two lifecycle functions componentDidMount and componentDidUpdate to the counter Demo in the original way. The counter results are printed on the browser console after the first rendering of the component and after each counter state change, respectively. The code is as follows:

import React, { Component } from 'react';

class Example3 extends Component {
    constructor(props) {
        super(props);
        this.state = { count:0 }
    }
    
    
    componentDidMount(){
        console.log(`ComponentDidMount=>You clicked The ${this.state.count} times`)
    }
    componentDidUpdate(){
        console.log(`componentDidUpdate=>You clicked The ${this.state.count} times`)
    }

    render() { 
        return (
            <div>
                <p>You clicked {this.state.count} times</p>
                <button onClick={this.addCount.bind(this)}>Chlick me</button>
            </div>
        );
    }
    addCount(){
        this.setState({count:this.state.count+1}}})export default Example3;


Copy the code

This is how to write without Hooks, how to replace this code with Hooks and have the same effect.

withuseEffectFunction instead of life cycle function

In the case of React Hooks, we can implement the lifecycle effects of the above code with the following code (modified from diamond) : Remember to use the useEffect first.

import React, { useState , useEffect } from 'react';
function Example(){
    const [ count , setCount ] = useState(0);
    //-- key code ---------start-------
    useEffect((a)= >{
        console.log(`useEffect=>You clicked ${count} times`)})//-- key code ---------end-------

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()= >{setCount(count+1)}}>click me</button>
        </div>)}export default Example;

Copy the code

Once written, you can preview it in a browser and see that it is exactly the same as the life cycle function in class form, which means that it is executed on the first component rendering and every component update. So what’s the logic of this code? First, we create a state variable, count, and set its initial value to 0. Then we tell React that our component has a side effect. We sent useEffecthook an anonymous function, and that anonymous function is our side effect. Here we print a sentence, but you can also manually modify a DOM element. When React renders a component, it remembers the side effects used and executes them once. When the Reat updates the State, it then executes the defined side effect function.

UseEffect two points

  1. React The useEffect function is called for the first rendering (componentDidMonut) and for every subsequent rendering (componentDidUpdate).

  2. UseEffect defines functions that execute asynchronously without preventing the browser from updating the view, whereas the code in componentDidMonut and componentDidUpdate are executed synchronously. Personally, I think this has both advantages and disadvantages. For example, we need to draw the size of the current pop-up window according to the size of the page. If it is asynchronous, it will be difficult to operate.

In this lesson we will learn about the useEffect function in React Hooks.

P04:useEffect implements componentWillUnmount life cycle function

When writing React applications, the componentWillUnmount life cycle function (executed when the component is about to be unmounted) is often used in components. For example, our timer should be emptied to avoid memory leaks. For example, the login status should be cancelled to avoid the error of entering information next time. Therefore, this life cycle function is also necessary. In this lesson, we will use useEffect to implement this life cycle function and explain the pits that useEffect is easy to step on.

UseEffect Unbinding side effects

ComponentWillUnmount = componentWillUnmount = componentWillUnmount = componentWillUnmount = componentWillUnmount = componentWillUnmount = componentWillUnmount Here in order to demonstrate the useEffect to achieve similar componentWillUnmount effect, install the react-router route first, enter the project directory, use NPM to install.

npm install --save react-router-dom
Copy the code

Then open example. js and rewrite the code to introduce the react-router component.

import { BrowserRouter as Router, Route, Link } from "react-router-dom"
Copy the code

Write two new components in a file. Because both components are so simple, you don’t have to create a separate file to write them.

function Index() {
    return <h2>JSPang.com</h2>;
}
  
function List() {
    return <h2>List-Page</h2>;
}

Copy the code

With these two components in place, you can write the routing configuration, which can be added directly to the previous counter code.

return( <div> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> <Router> <ul> <li> < Link to = "/" > home page < / Link > < / li > < li > < Link to = "/ list/" > list < / Link > < / li > < / ul > < the Route path ="/" exact component = {Index} / > <Route path="/list/" component={List} /> </Router> </div> )Copy the code

Then take a look in your browser to see if the components and routes are available. If available, we can now adjust the useEffect. Add the useEffect() function to the two new components:


function Index() {
    useEffect((a)= >{
        console.log('useEffect=> Buddy, there you are! The Index page '))return <h2>JSPang.com</h2>;
}
  
function List() {
    useEffect((a)= >{
        console.log('useEffect=> Buddy, there you are! A List page ')})return <h2>List-Page</h2>;
}

Copy the code

Click Link to enter any component and the browser will print out the corresponding text. This can be done by returning a function as follows:

function Index() {
    useEffect((a)= >{
        console.log('useEffect=> There you are, buddy! The Index page ')
        return (a)= >{
            console.log('Buddy, you're gone! The Index page ')}})return <h2>JSPang.com</h2>;
  }
Copy the code

Now when you preview it in the browser, it looks like we’ve implemented the componentWillUnmount method. But it just seems to work, and when you hit the counter button, you’ll find, boy, you’re gone! The Index page also appears. What the hell is going on here? In fact, useEffect is used every time the state changes.

UseEffect is the second parameter

How to achieve similar componentWillUnmount effect that? The second argument to useEffect is an array of variables that can be written to the state, meaning that we unbind only when the state value changes. But when an empty array [] is passed, the component is unbound only when it is about to be destroyed, which implements the life cycle function for componentWillUnmount.

function Index() {
    useEffect((a)= >{
        console.log('useEffect=> There you are, buddy! The Index page ')
        return (a)= >{
            console.log('Buddy, you're gone! The Index page ')}}, [])return <h2>JSPang.com</h2>;
}
Copy the code

To get a better idea of what the second parameter does, add the useEffect unbinding method to the counter code and an empty array for the second parameter. The code is as follows:

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

    useEffect((a)= >{
        console.log(`useEffect=>You clicked ${count} times`)

        return (a)= >{
            console.log('= = = = = = = = = = = = = = = = = = = =')}}, [])return( <div> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> <Router> <ul> <li> < Link to = "/" > home page < / Link > < / li > < li > < Link to = "/ list/" > list < / Link > < / li > < / ul > < the Route path ="/" exact component = {Index} / > <Route path="/list/" component={List} /> </Router> </div> ) }Copy the code

The code cannot perform unbinding side effects. But if we wanted to unbind every time count changed, we would just add the count variable to the second parameter array. The code is as follows:

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

    useEffect((a)= >{
        console.log(`useEffect=>You clicked ${count} times`)

        return (a)= >{
            console.log('= = = = = = = = = = = = = = = = = = = =')
        }
    },[count])

    return( <div> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> <Router> <ul> <li> < Link to = "/" > home page < / Link > < / li > < li > < Link to = "/ list/" > list < / Link > < / li > < / ul > < the Route path ="/" exact component = {Index} / > <Route path="/list/" component={List} /> </Router> </div> ) }Copy the code

Whenever the count state changes, the unbinding side effect function is executed, and the browser console prints out a string of =================.

Using the React Hooks function to write components is the same as using Class to write components. Use the react-hooks function to write components. But that’s not everything that Hooks has, and there are a few new features that will surprise us. That’s it. Next time, we’ll continue on to React Hooks.

P05:useContext makes it easier for parent and child components to pass values

UseState and useEffect already implement most of the business logic, but there are many Hooks functions in React Hooks, such as useContext and useReducer.

When a component is declared using a class, the parent component passes values through the component properties and props. If a component is declared using a Function, the constructor is not used and props is not received, so the parent component passes values becomes a problem. React Hooks prepared useContext for us. In this lesson, we’ll take a look at useContext, which allows us to share variables directly across the component hierarchy. It is important to note that useContext and Redux have different functions. One resolves the problem of value transfer between components, while the other manages the state of applications uniformly. However, using useReducer together with useContext can achieve functions similar to Redux.

This is like playing a game when there are many heroes, the main purpose of the hero is to win the match, but the role of different heroes, some are responsible for output, some are responsible for damage resistance, some are responsible for healing.

Context is a technique for providing globally shared data to the tree of components it contains.

CreateContext creates the context

Simply create a new file example4.js in the SRC directory, copy the example.js code and modify it, removing the routing and side effects, leaving only the core counter code.

import React, { useState , useEffect } from 'react';

function Example4(){
    const [ count , setCount ] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()= >{setCount(count+1)}}>click me</button>
        </div>)}export default Example4;

Copy the code

Then modify index.js to render the example4.js component as follows.

import React from 'react';
import ReactDOM from 'react-dom';
import Example from './Example4'
ReactDOM.render(<Example />, document.getElementById('root'));

Copy the code

We then introduce the createContext function in example4.js and use it to get a component and use it in the return method. Look at the code first, and then I’ll explain.


import React, { useState , createContext } from 'react';
//=== critical code
const CountContext = createContext()

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

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()= >{setCount(count+1)}}>click me</button>{/*====== */}<CountContext.Provider value={count}>
            </CountContext.Provider>

        </div>
    )
}
export default Example4;

Copy the code

This code allows the count variable to be passed and used across hierarchies (that is, the context is implemented), and when the parent component’s count variable changes, the child component changes as well. Let’s look at how a React Hooks component receives this variable.

UseContext receives context variables

Now that the context variable is in place, all that remains is how to receive it. You can receive it using useContext, but you need to import useContext before using it.

import React, { useState , createContext , useContext } from 'react';

Copy the code

After introducing, write a Counter component that simply displays the count variable in context as follows:

function Counter(){
    const count = useContext(CountContext)  // We can get count in one sentence
    return (<h2>{count}</h2>)}Copy the code

When you get it, you can display it, but remember that in the closing tag of < countContext. Provider>, the code looks like this.

<CountContext.Provider value={count}>
    <Counter />
</CountContext.Provider>
Copy the code

In fact, the usage of useContext is much easier than before. Since it is simple, there is no need to explain it so difficult. I hope that all friends can get knowledge points in this class and improve their knowledge system.

P06: Introduction and simple use of useReducer

Since the useContext function is similar to the useContext function, useReducer and useReducer can work together to perform similar operations in the Redux library. Using useReducer in development makes the code more readable and maintainable, as well as easier to test. Let’s take a thorough look at useReducer. In this lesson, we will simply take a look at the syntax and usage of useReducer and try to avoid some of the operations of Redux. This is easier for people who don’t know Redux to accept.

What exactly is Reducer?

In order to better understand useReducer, it is necessary to understand what Redcuer is in JavaScript. Its rise began when Redux was widely used, but not only in Redux, but also using Gunn’s JavaScript to complete Reducer operations. Reducer is actually a function that receives two parameters, one is the state and the other is the judgment parameter used to control the business logic. Let’s take the simplest example.

function countReducer(state, action) {
    switch(action.type) {
        case 'add':
            return state + 1;
        case 'sub':
            return state - 1;
        default: 
            returnstate; }}Copy the code

The above code is Reducer. What you mainly understand is this form and the role of two parameters, one is the state and the other is how to control the state.

The use of useReducer

After understanding the definition of reducer, we can talk about useReducer, which is also a function provided by React hooks to enhance our Reducer and achieve functions similar to Redux. Let’s create a new example5.js file and use useReducer to add and subtract counters in both ways. (Watch the video for an introduction to this part of the code)

import React, { useReducer } from 'react';

function ReducerDemo(){
    const [ count , dispatch ] =useReducer((state,action) = >{
        switch(action){
            case 'add':
                return state+1
            case 'sub':
                return state- 1
            default:
                return state
        }
    },0)
    return (
       <div>
           <h2>Now the score is {count}</h2>
           <button onClick={()= >dispatch('add')}>Increment</button>
           <button onClick={()= >dispatch('sub')}>Decrement</button>
       </div>)}export default ReducerDemo

Copy the code

This code is the simplest implementation of useReducer, this time can be implemented in the browser counter increase and decrease.

Modify the index.js file to make the ReducerDemo component work.

import React from 'react';
import ReactDOM from 'react-dom';
import Example from './Example5'


ReactDOM.render(<Example />, document.getElementById('root'));

Copy the code

In the next lesson, we will use a specific example to implement a similar use of useReducer.

P07:useReducer instead of Redux small case -1

It is possible to use useContext and useReducer to achieve a similar effect to Redux, and some simple personal projects can completely replace Redux with the following solution, which is easier than Redux. Since useContext and useReducer have been studied in the previous two classes, we will focus on how to simulate the effect of Redux. If you don’t already know the basics of grammar, review the previous two sections.

This lesson is based on an article by Miao Yu on the Nuggets website, juejin.cn/post/684490…

Theoretical feasibility

Let’s take a theoretical look at the possible alternatives to Redux, but if you know something about the two functions, it’s perfectly possible if we combine them nicely.

UseContext: Provides access to global state, avoiding layers of state passing. This conforms to one of the Redux rules, which is that state is global and managed uniformly.

UseReducer: Updates the status of complex logic through action transmission, mainly to achieve the Reducer part in Redux to achieve the feasibility of service logic.

After our theoretical analysis is completely feasible, we will use a simple example to see the specific implementation method. In this lesson, we will implement the useContext part (state sharing) and continue with the useReducer part (controlling business logic).

Write basic UI components

Since it is an example, you need some interface things, friends do not feel bored. Create a new folder Example6 under the/SRC directory, and then create a showarea.js file under the folder. The code is as follows:

import React from 'react';
function ShowArea(){
   
    return (<div style={{color:'blue'}} >The font color is blue</div>)}export default ShowArea

Copy the code

Once the display area is complete, create a new buttons. js file to write Buttons. Here are two Buttons, one red and one yellow. Don’t write any other business logic for now.

import React from 'react';

function Buttons(){
    return (
        <div>
            <button>red</button>
            <button>yellow</button>
        </div>)}export default Buttons
Copy the code

Then write a composite example6.js component that introduces two newly written components, ShowArea and Buttons, wrapped in a

tag.
import React, { useReducer } from 'react';
import ShowArea from './ShowArea';
import Buttons from './Buttons';


function Example6(){
    return (
        <div>
                <ShowArea />
                <Buttons />
        </div>)}export default Example6
Copy the code

After this step, you need to import the example6.js file in/SRC to React to render the UI component you just wrote.

import React from 'react';
import ReactDOM from 'react-dom';
import Example from './Example6/Example6'


ReactDOM.render(<Example />, document.getElementById('root'));

Copy the code

After this step, you can simply preview the UI, which is ugly, but as long as it meets your learning needs. Although we are front-end, but there is no need to pursue beautiful pages when learning, the key to understand the knowledge point. We write so many documents to serve the following knowledge, but these components are just a foil.

Write color sharing componentscolor.js

Now that you have the UI component, you can write some business logic, and in this lesson we’ll start with state sharing, which is using useContext. Create a color.js file and write the following code.

import React, { createContext } from 'react';

export const ColorContext = createContext({})

export const Color = props= >{
    return (
        <ColorContext.Provider value={{color:"blue}} ">
            {props.children}
        </ColorContext.Provider>)}Copy the code

The createContext is introduced to create the shared context ColorContext component, and we want to use {props. Children} to display the corresponding child component. I’ll explain it in detail in the video.

With this component in place, we can rewrite example6.js so that it can share state.

import React, { useReducer } from 'react';
import ShowArea from './ShowArea';
import Buttons from './Buttons';
import { Color } from './color';   // Introduce the Color component

function Example6(){
    return (
        <div>
            <Color>
                <ShowArea />
                <Buttons />
            </Color>
            
        </div>)}export default Example6
Copy the code

Then rewrite the showarea.js file to introduce useContext and the ColorContext declared in color.js so that the component can receive global variables.

import React , { useContext } from 'react';
import { ColorContext } from './color';

function ShowArea(){
    const {color} = useContext(ColorContext)
    return (<div style={{color:color}}>Font color is {color}</div>)}export default ShowArea

Copy the code

At this point, the state is shared through useContext, which can be viewed in the browser. And then we’ll implement complex logic state changes next time.

P08:useReducer instead of Redux small case -2

In this lesson, we will take a look at how to use useReducer to control the business logic. It should be noted that the content of this lesson is a continuation of the last lesson. You need to finish the code part of the last lesson before you can continue learning. If you don’t study, I believe you may not understand.

Add Reducer in color.js

We have put all the color state management codes in color.js, so add a reducer in the file to handle the logic of color updates. First declare a reducer function, which is a normal function in JavaScript and has been discussed in detail in the useReducer class. With reducer, use the useReducer in the Color component, so that the Color component has the ability to share state and process business logic, almost the same as the previous Redux. Then modify the share status. Let’s look at the code:

import React, { createContext,useReducer } from 'react';

export const ColorContext = createContext({})

export const UPDATE_COLOR = "UPDATE_COLOR"

const reducer= (state,action) = >{
    switch(action.type){
        case UPDATE_COLOR:
            return action.color
        default:
            return state
    }
}


export const Color = props= >{
    const [color,dispatch]=useReducer(reducer,'blue')
    return (
        <ColorContext.Provider value={{color,dispatch}}>
            {props.children}
        </ColorContext.Provider>)}Copy the code

Note that the shared outgoing state is now color and Dispatch, and without the shared outgoing dispatch, you will not be able to complete the button event.

Change the status through Dispatch

Now that the program has the business logic to handle shared state, you can use dispatch in buttons.js to handle the buttons. Use useContext, ColorContext, and UPDATE_COLOR, and write the onClick event. The code is as follows:

import React ,{useContext} from 'react';
import {ColorContext,UPDATE_COLOR} from './color'

function Buttons(){
    const { dispatch } = useContext(ColorContext)
    return (
        <div>
            <button onClick={()= >{dispatch ({type: UPDATE_COLOR, color: "red"})}} > red</button>
            <button onClick={()= >{dispatch ({type: UPDATE_COLOR, color: "yellow"})}} > yellow</button>
        </div>)}export default Buttons

Copy the code

This code is completed, using useContext and useReducer to achieve the effect of Redux, this code writing process is simpler than Redux, but it is also a certain degree of difficulty. I hope that the first contact of partners can write more than 5 times by themselves, to master this mode.

P09:useMemo optimizes React Hooks program performance

UseMemo is primarily designed to address performance issues with useless rendering using React hooks. Using function to declare components loses the shouldCompnentUpdate (before component updates) lifecycle, which means there is no way to determine whether a component is updated by a condition before component updates. Moreover, the mount and update states are no longer distinct in function components, which means that every call to a function component executes all the internal logic, resulting in a significant performance penalty. Both useMemo and useCallback address the above performance issues, so this lesson starts with useMemo.

Examples of performance problems

Let’s write the performance problem we just mentioned, and set up two components, a parent component and a child component, which is composed of two buttons, one is small red, one is Zhi Ling, click which, that is like we are coming. In the/SRC folder, create a new Example7 folder, and create an example7.js file under that folder. Then write the first parent component first.


import React , {useState,useMemo} from 'react';

function Example7(){
    const [xiaohong , setXiaohong] = useState('Xiaohong hospitality status')
    const [zhiling , setZhiling] = useState('Zhiling Hospitality status')
    return (
        <>
            <button onClick={()= >{setXiaohong (new Date (). GetTime ())}} > little red</button>
            <button onClick={()= >{setZhiling (new Date (). GetTime () + ', tzu chi ling is coming to us')}} > chi ling</button>
            <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>
        </>)}Copy the code

The parent component calls the child component, and the child component outputs the status of the two girls to the interface. The code is as follows:

function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('Here she comes, here she comes. Little Red is coming to us. ')
        return name+'Here comes Red.'
    }

    const actionXiaohong = changeXiaohong(name)
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>)}Copy the code

The parent component is then exported so that index.js can be rendered.


export default Example7
Copy the code

In this case, you will find that when you click the zhiling button in the browser, the method corresponding to the red will be executed. Although the result is the same, it will be executed every time. This is the performance loss. Currently there are only sub-components and the business logic is very simple, which can have serious consequences if it is a background query. So the problem has to be solved. When we click the zhi Ling button, the changeXiaohong method corresponding to the little red cannot be executed, only when the little red button is clicked.

UseMemo optimizes performance

In fact, as long as you use useMemo, and then pass her the second parameter, the match is successful, will be executed. The code is as follows:

function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('Here she comes, here she comes. Little Red is coming to us. ')
        return name+'Here comes Red.'
    }

    const actionXiaohong = useMemo((a)= >changeXiaohong(name),[name]) 
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>)}Copy the code

Click the zhiling button in the browser at this time, changeXiaohong is no longer executed. It also saves performance costs. The case study just gives you a better understanding, and you have to see the optimization in the application itself. Good programmers will continue to optimize their own programs, such unnecessary performance waste is absolutely not allowed, so the use of useMemo in the work or more. I hope you can master it.

P10:useRef retrieves DOM elements and saves variables

UseRef isn’t used much, but it’s not missing. It has two main functions:

  • Get the React JSX DOM element with useRef. Once you get it, you can control anything in the DOM. However, this is not recommended. The React interface changes can be controlled by state.

  • Using useRef to save variables, which we don’t use very often in our work, we have useContext which doesn’t make a lot of sense, but it’s a learning feature, and we’ll talk about it too.

UseRef retrieves the DOM element

There is a text box on the interface, and there is a button next to the text box. When we click the button, the console prints out the DOM element of the input and copies it to the value in the DOM. This is all done through useRef.

Create a new example8.js file in the/SRC folder, import useRef first, and write the business logic as follows:

import React, { useRef} from 'react';
function Example8(){
    const inputEl = useRef(null)
    const onButtonClick=(a)= >{ 
        inputEl.current.value="Hello ,JSPang"
        console.log(inputEl) // Output the DOM node
    }
    return<input ref={inputEl} type="text"/> <button onClick = {onButtonClick}> Display text on input </button> </>)} export default Example8Copy the code

When you click the button, you can see that the console in the browser prints out everything in the DOM, and the box value on the interface also prints out the Hello,JSPang we wrote. All this means that you can use useRef to retrieve DOM elements and control DOM attributes and values through useRefu.

UseRef holds ordinary variables

This operation is not used much in real development, but we will explain it anyway. UseRef can store variables in React. So let’s just write a text box here, and the text box will change the text state. Use useRef to save the text state, and finally print it on the console. Writing this code will make you feel very convoluted, but it is not necessary to write this code in display development, using a state state can be done, just to show the knowledge.

Following the above code, there is no need to write a new file. Use useState to declare a text state and a setText function. And then you write the interface, which is just a text box. And then it keeps changing as you type it in.

import React, { useRef ,useState,useEffect } from 'react';



function Example8(){
    const inputEl = useRef(null)
    const onButtonClick=(a)= >{ 
        inputEl.current.value="Hello ,useRef"
        console.log(inputEl)
    }
    const [text, setText] = useState('jspang')
    return<input ref={inputEl} type="text"/> <button onClick = </button> <br/> <br/> <input value={text} onChange={(e)=>{setText(e.target.value)}} /> </> } export default Example8Copy the code

You want to save the text to a variable, or useRef, every time it changes state. Start by declaring a textRef variable, which is essentially the useRef function. The useEffect function is then used to modify the variables for each state change and print. The final code is as follows.

import React, { useRef ,useState,useEffect } from 'react';
function Example8(){
    const inputEl = useRef(null)
    const onButtonClick=(a)= >{ 
        inputEl.current.value="Hello ,useRef"
        console.log(inputEl)
    }
    //----------- key code --------start
    const [text, setText] = useState('jspang')
    const textRef = useRef()

    useEffect((a)= >{
        textRef.current = text;
        console.log('textRef.current:', textRef.current)
    })
    //---------- key code --------------end
    return<input ref={inputEl} type="text"/> <button onClick = </button> <br/> <br/> <input value={text} onChange={(e)=>{setText(e.target.value)}} /> </> } export default Example8Copy the code

At this point, each state change can be implemented and saved to useRef. That’s what we call saving variables. So useRef’s main function is to get the DOM and save variables, which we’ve already talked about. Your coding ability has increased a bit, let’s work together.

P11: Custom Hooks function to get window size

In fact, custom Hooks functions are similar to building components using Hooks. They are almost the same as writing functions in JavaScript, except that they have some React Hooks. Custom Hooks function for functionality, components for interface and business logic. Since there is not much difference, it is also very casual to use. This is fine if the project is small, but if the project is complex enough, the structure of the project is not clear. So it’s important to learn about custom Hooks functions.

Write custom functions

In the actual development, in order to interface more beautiful. Getting the size of the browser window is a frequently used function, so that frequently used functions can be wrapped in a custom Hooks function. Remember to start with use to distinguish between components and custom functions.

Create a new file example9.js and write useWinSize, which uses useState, useEffect and useCallback, so import first.

import React, { useState ,useEffect ,useCallback } from 'react';
Copy the code

Then write a function that uses useState to set the size state, and then write a method onResize that changes the state each time. This method uses useCallback to cache the method (useMemo is used to cache variables). UseEffect is then used to register the resize listening time the first time the method is entered. To prevent constant listening, return is used to remove listening when the method is removed. Finally, return the size variable.

function useWinSize(){
    const [ size , setSize] = useState({
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })

    const onResize = useCallback((a)= >{
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        })
    },[]) 
    useEffect((a)= >{
        window.addEventListener('resize',onResize)
        return (a)= >{
            window.removeEventListener('resize',onResize)
        }
    },[])

    return size;

}

Copy the code

This is a custom function, in fact, and we wrote before JS function is no different, so there is not too much introduction.

Write components and use custom functions

Custom Hooks functions have been written and can be used directly, using the same usage as normal JavaScript functions. Use useWinSize directly on the Example9 component and display the results in real time on the page.

function Example9(){

    const size = useWinSize()
    return (
        <div>Page Size: {Size. Width} {x the Size, height}</div>)}export default Example9 

Copy the code

You can then preview the results in your browser and see that the results on the page change as we zoom in and out of the browser window. Note The user-defined function takes effect.