Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

📢 Hello everyone, I am Xiao Cheng, a sophomore front-end enthusiast

📢 This article is a study note for the Learn React extension

📢 Thank you very much for reading

📢 May you be true to yourself and love life

The introduction

React Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts Reacts React-hook: react-hook: react-hook: react-hook: react-hook: react-hook: react-hook:………….

Therefore, Hooks need to be studied in depth, so let’s see what the extensions are

1. setState

Object type setState

First of all, in our previous knowledge, setState is used to update the state, and we usually pass it an object, like this

this.setState({
    count: count + 1
})
Copy the code

Each update will increase the value of count by one. And that’s what we make the most

So let’s do an example here, click I add one, one value per button, and I’m going to print the value of count every time on the console

So we need to output on the console, how do we do that?

We’ll consider logging after the setState update

add = () = > {
    const { count } = this.state
    this.setState({
        count: count + 1
    })
    console.log(this.state.count);
}
Copy the code

So it might seem reasonable to write code that prints count after calling setState

We found that the count displayed was different from the count output from our console

React does not update data immediately. This is an asynchronous task, so the output count value will be the data before the status update. React Status updates are asynchronous

So how do we synchronize?

In fact, the second argument to the setState call, we can receive a function that will be called after the state update and the interface update, so we can try that

add = () = > {
    const { count } = this.state
    this.setState({
        count: count + 1
    }, () = > {
        console.log(this.state.count)
    })
}
Copy the code

We fill in setState with the second argument and print the updated count value

Then we can successfully get the latest data, if there is a need we can output in the second parameter oh ~

Functional setState

I’ve never seen this used before, and the functional setState also takes two arguments

The first argument is updater, which is a function that returns a stateChange object

The second argument is a callback function that is called after the status update is complete and the interface is updated

Unlike object setState, the first argument we pass updater receives two arguments, state and props

Let’s try it out

add = () = > {
    this.setState((state) = > ({ count: state.count + 1}}))Copy the code

And we managed to do that

We pass in the first parameter a function that receives state, and we drive the page update by updating the count value in state

It’s nice to take advantage of the function setState to get the props and state directly

It can be understood that object setState is the syntactic sugar of function setState

2. LazyLoad

The most common use of React is the routing component. When a page is refreshed, all the pages are reloaded. This is not what we want

We can see that all the routing components are loaded as soon as our page loads

If we have 100 routing components and the user only clicks on a few, that’s a lot of overhead, so we need to do lazy loading, which one we click on, which one we load

First we need to expose a lazy function from the React library

import React, { Component ,lazy} from 'react';
Copy the code

Then we need to change the way we import components

const Home = lazy(() = > import('./Home'))
const About = lazy(() = > import('./About'))
Copy the code

Wrap with a lazy function

We get an error that prompts us to wrap with a label

This is because when the network speed is slow, the routing component may not load, and the page will be blank. It requires us to specify what a routing component loads, as opposed to loading

<Suspense fallback={<h1>loading</h1>} ><Route path="/home" component={Home}></Route>
    <Route path="/about" component={About}></Route>
</Suspense>
Copy the code

When you do this example, make sure you don’t set the redirection thing, all the routes we’re going to hit reload

The first time you log in to the page

Note that these files are not routing components and will only be loaded when we click on the component

As you can see from the figure above, the chunk file is requested only when clicked

So what’s the use of our new fallback? It will be displayed when the page has not yet loaded

Note: Loading must be introduced in advance because it is used as a cushion

3. Hooks

useState

Hooks resolve the difference between functional components and class components, give functional components the same state as class components, and add new apis to make functional components more flexible

First we need to be clear that functional components do not have their own this

function Demo() {
    const [count, setCount] = React.useState(0)
    console.log(count, setCount);
    function add() {
        setCount(count + 1)}return (
        <div>
            <h2>The current sum is: {count}</h2>
            <button onClick={add}>I add 1 point</button>
        </div>)}export default Demo
Copy the code

Using functional components to complete the point I add 1 case

One Hook is used here: useState

It allows functional components to maintain their own state by taking an argument as the value of the initial state and assigning it to count, so the initial value of useState is only valid the first time, The two variables that it maps to count and setCount can be understood as setState

UseState can return an array with state as the first element and a function to update state as the second

So what do we get out of the console first

Count is the initialized value, and setCount is like an Action object that drives a status update

We can update the value of count by setCount

setCount(count + 1)
Copy the code

useEffect

In class components, there are declarative cycle hooks that we can use to do certain things at particular times of the component, such as componentDidMount, which can do things after the component has been mounted

In the functional components can also be realized, it uses effectHook, its grammar is more simple, while the integration of componentDidUpdata life cycle, great convenience of our development

React.useEffect(() = > {
    console.log('Called');
})
Copy the code

Because of the nature of functions, we can write functions in functions as we like. Here we call the useEffect function, which has several functions

When used like the code above, it is equivalent to using componentDidUpdata with componentDidMount, which is called when the component is mounted and updated

It can also receive a second parameter that represents the data it is monitoring, which changes it is monitoring

When we don’t need to listen for any state changes, we can just pass an empty array so that it can be used as componentMidMount

React.useEffect(() = > {
    console.log('Called');
}, [])
Copy the code

So we only fire when the component is first mounted

Of course, when there are multiple data sources on a page, we can also select individual data to monitor to achieve the desired effect

React.useEffect(() = > {
    console.log('Called');
}, [count])
Copy the code

In this way, we only monitor changes in the count data

When we want to do some timer cleanup before uninstalling a component, for class components we call the lifecycle hook componentDidUnmount. For functional components, we write it simpler. We’ll just implement it in the return value of the first argument to useEffect that is, the body of the first argument is equal to componentDidMount and the return body is equal to componentDidUnmount, so we can implement something that will output when the component is about to be unloaded

Implement uninstall

function unmount() {
    ReactDOM.unmountComponentAtNode(document.getElementById("root"))}Copy the code

Pre-uninstallation output

React.useEffect(() = > {
    console.log('Called');
    return () = > {
        console.log('I'm about to be unloaded.');
    }
}, [count])
Copy the code

Implements output when a component is about to be uninstalled

UseEffect is therefore equivalent to three life cycle hooks, componentDidMount, componentDidUpdata, and componentDidUnmount

useRef

When we want to get information from a component, in a class component, we use a REF to get it. In a functional component, we can useRef or ref, but we need to use the useRef function to create a ref container, which is similar to createRef.

<input type="text" ref={myRef} />
Copy the code

For ref value

function show() {
    alert(myRef.current.value)
}
Copy the code

The value in the input box is successfully retrieved

4. Fragment

We need to wrap a div tag every time we write a component in order for it to compile properly, but what problems does that cause? Let’s open up the console and look at its hierarchy

It wraps several layers of meaningless DIV tags, which we can solve with fragments

First, we need to expose the Fragment from react and wrap our content in the Fragment tag. When it is resolved to the Fragment tag, it will be removed

So our content hangs directly under the root tag

This can be done with an empty tag, but it can’t accept any values, whereas the Fragment can accept a key

5. Context

Applies only to class components

When we want to pass data to a subclass of a subclass, we talked about redux earlier, and the Context that we’re going to introduce here is similar to REdux, I think

First we need to introduce a MyContext component, and we need to reference the Provider in MyContext

const MyContext = React.createContext();
const { Provider } = MyContext;
Copy the code

Wrap component B in component A with the Provider label and pass the data to the child components using the value value. In this way, all the child components of component A can receive the data

<Provider value={{ username, age }}>
    <B />
</Provider>
Copy the code

But we need to introduce MyContext in components that use data

static contextType = MyContext;
Copy the code

When used, the value is directly from this.context

const {username,age} = this.context
Copy the code

Applies to functions and class components

Since functional components don’t have their own this, we can’t get data through this.context

Here we need to expose a Consumer from the Context

const { Provider ,Consumer} = MyContext;
Copy the code

And then value

function C() {
  return (
    <div>
      <h3>I'm component C and I'm receiving data from A</h3>
      <Consumer>{(value) = > {return ` ${value. The username}, age is ${value. The age} `; }}</Consumer>
    </div>
  );
}
Copy the code

So to use it in functional components, you need to introduce Consumer

6. PureComponent

In the code we’ve been writing, the Component we’ve been using is problematic

  1. As long as the executionsetStateThe component is called even if the state data is not changedrender
  2. Current component state updates also cause child componentsrender

We want render to be called only when the component’s state or props data changes

We can override shouldComponentUpdate, but this method does not solve the problem, when there are many states, there is no way to add judgment

We can use PureComponent

We can expose the PureComponent from react without using Component

import React, { PureComponent } from 'react'
Copy the code

There is only one PureComponent

The PureComponent compares the prop and state of the current object to the next state. The comparison is shallow, comparing whether the base data type is the same, while the reference data type compares whether its reference address is the same, regardless of the content

7. render props

Using the render props technique, we can dynamically pass in structures with content inside components

When we fill in a component tag, the content is defined as children props, and we can get this.props. Children

Such as:

<A>hello</A>
Copy the code

We can get this hello from children

Render props is called render props, because it is props, passing a render method in the component tag

<A render={(name) = > <C name={name} />} / >Copy the code

You can think of Render as props, but it has special functions, and it can also be called something else

{this.props. Render (name)} in the above code, we need to reserve the rendering location for the C component in the A component and add {this.props. Render (name)} to the desired location.

How do we receive the name value from component A in component C? This.props. Name

8. ErrorBoundary

When the data is abnormal due to uncontrollable factors, we cannot directly present the error page to the user. Since we cannot add judgment to every component and every file to ensure normal operation, it is unrealistic, so we need to use error boundary technology

Error boundaries minimize the impact of this component’s error and do not affect the normal operation of other components or the global system

For example, component A reports an error. We can add A short message to component A and control the error within component A without affecting other components

  • We want to tamper with the error-prone component’s parent, not the component itself

We use getDerivedStateFromError in the parent component to configure the handler when the child component fails

static getDerivedStateFromError(error) {
    console.log(error);
    return { hasError: error }
}
Copy the code

We can configure hasError to state. When hasError state changes to ERROR, it indicates that an error has occurred. We need to specify whether to display the child component by judging hasError value in the component

{this.state.hasError ? <h2>Error!</h2> : <Child />}
Copy the code

Start in the server to see the normal effect

Errors can be counted in componentDidCatch to inform the coder of bug resolution

9. Summary of component communication modes

  1. props
    • children props
    • render props
  2. Message publishing subscription
    • Use pubSub library to achieve
  3. Centralized state management
    • redux
  4. conText
    • Producer – consumer

Choose way

The parent and child components use: props

The sibling component uses: message publish subscribe, redux

Grandparent components: message publishing and subscription, Redux, Context