The React based article

A,setState

1. Use it correctlysetState

Because data is bidirectional binding, frequent operations on data will trigger the continuous refresh of DOM pages. If there is a large amount of data, it will also cause lag, which will consume a lot of performance. Therefore, React officially uses the setState function to update data in batches

setState(partialState, callback)

  1. partialState: object| function

    Used to generate subsets from the current state merge.

  2. callback: function

    The state is called after the update

About 2.setState()The three things

Do not modify State directly

For example, this code does not re-render the component:

// Error
this.state.comment = 'hello'
Copy the code

Instead, use setState():

// Use it correctly
this.setState({comment:'Hello'})
Copy the code
Updates to State can be asynchronous

React may combine multiple setState() calls into a single call for performance reasons

import React, { Component } from 'react'
export default class SetStatePage extends Component {
   	constructor(props) {
        super(props);
        this.state = {
            counter: 0
        }
    }
    changeValue = v= > {
        this.setState({
            counter: this.state.counter + v
        })
        console.log('counter'.this.state.counter)
    }
    render() {
        const { counter } = this.state
        return ( 
        	<div>
            	<h3>SetStatePage</h3>
            	<button onClick={this.setCounter}>{counter}</button>
            </div>)}}Copy the code

To get the latest status value, do the following:

  1. Get the status value in the callback

    changeValue = v= > {
        this.setState({
            counter: this.state.counter + v
        }, () = >{
            console.log('counter'.this.state.counter)
        })
    }
    Copy the code
  2. Use timer

    setTimeout(() = >{
        this.changeValue();
    })
    Copy the code
  3. Modify state in native event

    componentDidMount() {
        docment.body.addEventLister('click'.this.changeValue, false);
    }
    Copy the code
Conclusion:setStateAsynchronous only in synthesized events and lifecycle functions, in native events andsetTimeoutAre synchronous, asynchronous here is actually batch update.
StateUpdates are merged
changeValue = v= > {
    this.setState({
        counter: this.state.counter + v
    })
}
setCounter = () = > {
    this.changeValue(1);
    this.changeValue(2);
}
Copy the code

If you want to chain update the state

changeValue = v => {
	this.setState(state=>({counter: state.counter + v }));
}
setCounter = () => {
	this.changeValue(1);
	this.changeValue(2);
}
Copy the code

Component life cycle

Lifecycle methods for performing custom functionality in different phases of a component. Lifecycle methods are available when components are created and inserted into the Dom (mounting phase), when components are updated, when components are unmounted, or deleted from the Dom.

Life cycle after V16.4:

The three lifecycle functions that may be deprecated in V17 will be replaced with getDerivedStateFromProps and UNSAFGE_ if currently used:

  • componentWillMount
  • componentWilReceiveProps
  • componentWillUnUpdate

Introduce two new lifecycle functions:

  • static getDerivedStateFromProps
  • getsnapshotBeforeUpdate

Two new lifecycle functions introduced

getDerivedStateFromPropos
static getDerivedStateFromProps(nextProps, preState) 
Copy the code

GetDerivedStateFromProps is called before Render and will be called during initial mount and subsequent updates. It should return an object to update state, and if null is returned, nothing is updated

Note that this method fires before each render, regardless of the cause. This time,

Contrast this with UNSAFE_componentWillReceviProps, which only fires when the parent component is re-rendered, not when setState is called internally.

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate(preProps, preveState)

After Render, before componentDidUpdate.

GetSnaopshotBeforeUpdate () is called before the last render output (submitted to the Dom node). It allows the component to capture information from the Dom (for example, scroll position) before an update occurs. Any return value for this life cycle is passed as a parameter componentDidUpdate(preProps, prevState, Snapshot).

Three,Redux

Redux is a state container for JavaScript applications that provides predictable state management. It ensures consistent program behavior and is easy to test.

Practical case:

1. Need a store to store data 2. Initialize state and define state modification rules on reducer in the store 3. Submit changes to the data by dispatching an action. 4. Submit the action to the Reducer function and return the new state based on the type of the incoming actionCopy the code

Create a store, the SRC/store/ReaduxStore. Js

import { createStore } from 'redux'
const counterReducer = (state=0, action) = > {
    switch(action.type) {
        case 'ADD':
            return state + 1
        case 'MINUS':
            return state - 1
         default : 
            return state
    }
}
const store = createStore(counterReducer)
export default store
Copy the code

Create ReducPage

import React, { Component } from "react";
import store from ".. /store/ReduxStore";
export default class ReduxPage extends Component {
 componentDidMount() {
     store.subscribe(() = > {
         console.log("subscribe");
         this.forceUpdate();
     });
 }
 add = () = > {
 	store.dispatch({ type: "ADD" });
 };
 minus = () = > { store.dispatch({ type: "MINUS" });
 render() {
     console.log("store", store);
     return (
         <div>
             <h3>ReduxPage</h3>
             <p>{store.getState()}</p>
             <button onClick={this.add}>add</button>
             <button onClick={this.minus}>minus</button>
         </div>); }}Copy the code

If the button is clicked, it cannot be updated because there is no subscribe status change

You can also subscribe to state changes in SRC /index.js render

import store from './store/ReduxStore'
const render = () = >{
    ReactDom.render(
    <App/>.document.querySelector('#root')
    )
}
render()
store.subscribe(render)
Copy the code

Fourth, the react – story

React-redux is based on memory redux repackaged specifically for React.

Use the react – story

  1. ProviderProvide stores for descendant components
  2. connectProvide data and change methods to components

Global provides store,index

src/index.js

import React from 'react'
import ReactDom from 'reacat-dom'
import App from './App'
import store from './store/'
import { Provider } from 'react-redux'

ReactDom.render(
    <Provider store = {store}>
    	<App/>
    <Provider>,
    docment.getElementById('root')
)

Copy the code

store

import { crateStore } from 'redux'

// Define state initialization and modification rules,reduce is a pure function

function counterReducer (state = 0, action) {
    switch(action.type) {
        case "ADD":
            return state + 1;
        case "MINUS":
            return state - 1;
        default: 
            returnstate; }}const store = createStore(counterReducer)

export default store;
Copy the code

App.js

import React from 'react'
import ReactReduxPage from './pages/ReactReduxPage'

export default function App() {
    return (
    <div>
        <ReacatReduxPage/>
    </div>)}Copy the code

ReactReduxPage.js

import React, { Component } from 'react';

export default connect(
  //mapStateToProps maps state to props
 state= > ({num: state})
 ,   
  // mapDispatchToProps maps Dispatch to props by default
  {
  	add:() = >({type:"ADD"}) 
  }
)( calss ReactReduxPage extends Componets {
    const { num, dispatch , add } = this.props;
    render() {
        return (
        	<div>
        		<h3> ReactReduxPage </h3>
           		<p>{num}</p>{/ *<button onClick={() = > dispatch({ type:"ADD" })}>add</button>* /}<button onClick={ add} >add</button>
            </div>)}})Copy the code

Fifth, the react – the router

preface

React-router contains three libraries, react-Router, react-router-dom, and react-router-native. The react-router provides the most basic routing functions. In practice, we do not install the React-Router directly. Instead, we choose to install the React-router-DOM (for browser use) or the React-router-native (for RN use) based on the application environment. Both react-router-DOM and react-router-native depend on the react-router. Therefore, the react-router is automatically installed during installation to create web applications

The installation

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

case

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, NavLink, Switch } from 'react-router-dom'
class UserPage extends Component {
    render() {
        return (
         <h2>The user center</h2>)}}class home extends Component {
    render() {
        return (
         <h2>Home page</h2>)}}class EmptyPage extends Component {
    render() {
        return (
         <h2>404</h2>)}}export default class homePage extends Component {
    render() {
        return (
            <div>
                <Router>
                    <NavLink to="/">Home page</NavLink>
                    <NavLink to="/user-page">The user center</NavLink>
            		<Switch>
                        <Route exact path="/user-page" component={UserPage} children={()= ><div>children</div>} render={()=><div>render</div>} / ><Route exact path="/" component={home}/>
                        <Route component={EmptyPage}/>
                    </Switch>
                </Router>
            </div>)}}Copy the code

Route renders content in three ways

Children > Component > render

children: fuc

Sometimes, if you need to render something regardless of whether the location matches or not, you can use children.

It works exactly the same as render, except that the location is rendered regardless of whether it matches.

render: fuc

But when you call render, you’re just calling the function.

Render only when the location matches

component: component

Render only when the location matches

404 pages

Set a route with no path at the end of the route list to indicate a match

   {/* Add the Switch to match only one */}	
   <Switch>
        {/* Add exact to the root route to achieve forward matching */}	
		<Route path="/" component={home}/>
        <Route exact path="/user-page" component={UserPage} />
        <Route component={EmptyPage}/>
   </Switch>
Copy the code

Six, PureComponent

Achieve performance optimization

ShouldComponentUpdata (shouldComponentUpdata

import React, { Component, PureComponent } from 'react'

export default class PureComponentPage extends PureComponent {
    constructor (props) {
        super(props)
        this.state = {
            count: 0.obj: { num: 0}}}setCount() {
        this.setState({
            count: 100.obj: {
                num: 100}})}render() {
        console.log('render')
        const { count }  = this.state
        return (
            <div>
                <h3>{count}</h3> 
                <button onClick={()= >{this. SetCount ()}} > change</button>
            </div>)}}Copy the code

Shallow comparison

The disadvantage is that you must use the class form, and be careful that the comparison is shallow

Compared with the Component

React.PureComponent is very similar to react.component.react.component.react.pureComponent. The difference is that shouldComponentUpdate() is not implemented in react.component.pureComponent, which is implemented in a shallow way to compare prop and state.

If you give the React component the same props and state, and the render() function renders the same content, using the React.PureComponent can improve performance in some cases.

Pay attention to

ShouldComponentUpdate () in react.pureComponent is only a superficial comparison of objects. If the object contains complex data structures, it is possible to produce incorrect alignment results because deep differences cannot be examined. Use React.PureComponent only if your props and state are simple, or call forceUpdate() when the underlying data structure changes to ensure that the component is properly updated. You can also consider using immutable objects to speed comparison of nested data.

In addition, shouldComponentUpdate() in react.pureComponent skips prop updates for all subcomponent trees. Therefore, make sure that all child components are “pure” components as well

Seven, Hook

Know the Hook

What is Hoook? Hook is a special function that lets you “Hook” into the React feature. For example, useState is a Hook that allows you to add state to the React function component.

When can I Hook? If you were writing a function component and realized you needed to add some state to it, the old idea was that you had to convert it to class. You can now use hooks in existing function components.

import React,{useState} from 'react'

export default function HookPage() {
    // Define a state variable called count with an initial value of 0
    const [count, setCount] = useState(0)
    return (
        <div>
            <h3>{count}</h3> 
            <button onClick={()= >> add setCount (count + 1)}</button>
        </div>)}Copy the code

Use Effect Hook

Effect Hook allows you to perform side effects in function components.

Fetching data, setting up subscriptions, and manually changing the Dom in the React component are all side effects. Whether or not you know these operations, or the name “side effects,” you’ve probably used them in components.

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

export default function HookPage() {
    const [count, setCount] = useState(0)
    useEffect(() = >{
        document.title = `You cliced ${count} times`
    })
    return (
        <div>
            <h3>{count}</h3> 
            <button onClick={()= >> add setCount (count + 1)}</button>
        </div>)}Copy the code

Changing the DOM, adding subscriptions, setting timers, logging, and performing other side effects within the body of a function component (in this case, during the React rendering phase) are not allowed, as this can cause unexplained bugs and break UI consistency.

Use useEffect for side effects. The function assigned to useEffect is executed after the component is rendered to the screen. You can think of Effect as an escape route from the purely functional world of React to the imperative world.

By default, effect is executed at the end of each render round. But you can choose to have it execute only when certain values change.

Effect conditional execution

By default, effect is executed at the completion of each round of component rendering. This way, the effect will be recreated as soon as its dependency changes.

However, there are situations where doing so can be a waste of time. For example, in the subscription example in the previous section, instead of creating a new subscription every time a component is updated, we only need to recreate it when the Source props changes.

To do this, you pass useEffect a second parameter, which is the array of values that Effect depends on. The following is an example of the update:

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

export default function HookPage() {
    const [count, setCount] = useState(0)
    const [date, setDate] = useState(new Date())
  
    useEffect(() = >{
        console.log('effect')
        document.title = `You cliced ${count} times`
    },[count])

    useEffect(() = >{
        const timer = setInterval(() = >{
            setDate(new Date()},1000)
    },[])
    return (
        <div>
            <h3>{count}</h3> 
            <h3>Time: {date. ToLocaleTimeString ()}</h3>
            <button onClick={()= >> add setCount (count + 1)}</button>
        </div>)}Copy the code

At this point, the subscription is recreated only if the value in the second parameter array of useEffect changes.

Clear effect

Typically, components uninstall with the need to clear resources such as subscriptions or timer ids created by Effect. To do this, the useEffect function returns a cleanup function to prevent memory leaks, which is executed before the component is unloaded.

   useEffect(() = >{
        const timer = setInterval(() = >{
            setDate(new Date()},1000)
        return () = >clearInterval(timer)
    },[])
Copy the code

Customize the Hook

Sometimes we want to reuse some state logic between components. So far, there are two main solutions to this problem: higher-order components and reader props. Custom hooks allow you to achieve the same goal without adding components.

A custom Hook is a function whose name starts with use. Other hooks can be called from within the function.

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

export default function HookPage() {
    const [count, setCount] = useState(0)
    useEffect(() = >{
        console.log('effect')
        document.title = `You cliced ${count} times`
    },[count])

    return (
        <div>
            <h3>{count}</h3> 
            <h3>Time: {useClock (.) toLocaleTimeString ()}</h3>
            <button onClick={()= >> add setCount (count + 1)}</button>
        </div>)}const useClock = () = > {
    const [date, setDate] = useState(new Date())
    useEffect(() = >{
        const timer = setInterval(() = >{
            setDate(new Date()},1000)
         return () = > clearInterval(timer)
    }, [])
    return date
}
Copy the code

Hook usage rules

Hooks are Javascript functions, but there are two additional rules for using them:

  • Call a Hook only from the outer layer of a function, never from a loop, a conditional judgment, or a child function.
  • You can only call a Hook in the React function component. Do not call it in any other Javscript function. (There is another place to call a Hook– a custom Hook.)

useMemo

Pass the “create” function and an array of dependencies as arguments to useMemo, which recalculates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render.

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

export default function useMemoPage() {
    const [count, setCount] = useState(0)
    
    const expensive = useMemo(() = > {
        console.log('expensive')
        let sum = 0;
        for(let i=0; i<count; i++){ sum+=i; }return sum
    }, [count])

    const [value, setValue] = useState(' ')
    return (
        <div>
            <h3>UseMemoPage</h3>
            <p>count: {count}</p>
            <p> expensive: {expensive} </p>
            <button onClick={()= >setCount(count+1)}>add</button>
            <input value={value} onInput={event= > setValue(event.target.value)} ></input>
        </div>)}Copy the code

useCallback

Passing the inline callback function and the array of dependencies as arguments to useCallback returns the Memoized version of the callback function, which is updated only when a dependency changes. This is useful when you pass callback data to child components that are optimized and use reference equality to avoid unnecessary rendering (such as shouldComponentUpdate).

import React, {useState, useCallback , PureComponent} from 'react'

export default function UseCallbackPage() {
    const [count, setCount] = useState(0)

    const addClick =useCallback(() = > {
        let sum = 0;
        for(let i=0; i<count; i++){ sum+=i; }return sum
    },[count]) 
    const [value, setValue] = useState(' ')
    return (
        <div>
            <h3>UseMemoPage</h3>
            <p>count: {count}</p>
            <button onClick={()= >setCount(count+1)}>add</button>
            <input value={value} onInput={event= > setValue(event.target.value)} ></input>
            <Children addClick={addClick} ></Children>
        </div>)}class Children  extends PureComponent {
    render() { 
        const { addClick } = this.props
        console.log('Children render')
        return( <div>
            <button onClick={()= >addClick}>add</button>
       </div>)}}Copy the code