React [Context_function, function component subscription Context, Fragments, error boundary_concept, error boundary_application, Refs & DOM] (4)

Table of contents

Context_role

Function component subscribes to Context

Fragments

 Error Boundary_Concept

 Error Boundary_Application

Refs & DOM


Context_role

 Data in React components is passed from top to bottom (from parent to child) through the props attribute, but sometimes some components in the middle may not need the value of props.

//App.js
return (
    <div>
      <ContextTest />
    </div>
 );
//ContextTest.js
import React from 'react'
import NavBar from './NavBar'
export default class ContextTest extends
React.Component{
    constructor(props){
        super(props)
        this.state={user:{name:'小童',account:'baizhan'}}
   }
    render(){
        return <div>
            <NavBar user={this.state.user}/>
        </div>
   }
}
//NavBar.js
import React, { Component } from 'react'
import UserInfo from './UserInfo'
export default class NabBar extends
Component {
  render() {
    return (
      <div style= {
   
   {height:'50px',background:'#ccc',display:'flex',justifyContent:'space-around',alignItems:'center'}}>
       NabBar的内容
        <UserInfo user={this.props.user}/>
        </div>
   )
 }
}

//UserInfo.js
import React, { Component } from 'react'
export default class UserInfo extends
Component {
  render() {
    return (
      <div>你好,欢迎 {this.props.user.account}</div>
   )
 }
}

Context provides a way to pass data between component trees without manually adding props for each layer of components.
 

When to use Context

If we want to share some data in the component tree and avoid passing props through intermediate elements, we can use Context.

Context_Application


 1. Create Context object

React.createContext(defaultValue)

const MyContext = React.createContext(defaultValue);

2. Provider component of Context

The Provider component of Contentxt is used to provide data to be shared by other components.
Set the value attribute to set the data to be shared.

<MyContext.Provider value={/* 某个值 */}>

3. Provider component of Context

The Provider component of Contentxt is used to provide data to be shared by other components.
Set the value attribute to set the data to be shared.

<MyContext.Provider value={/* 某个值 */}>

Tip: We call components that use shared data consuming components.

 Class.contextType

Add the contextType attribute to the component class to obtain the Context object.

MyClass.contextType = MyContext;

Tip: The contextType
attribute mounted on the class will be reassigned to a Context object created by React.createContext() . This allows you to use this.context to consume the value on the most recent Context . You can access it in any life cycle, including the render function.

//MyContext.js
import React from "react";


export default
React.createContext({name:'',account:'xxx'})

//ContextTest.js
import React from 'react'
import MyContext from './MyContext'
import NavBar from './NavBar'
export default class ContextTest extends
React.Component {
    constructor(props) {
        super(props)
        this.state = { user: { name: '小童',account: 'xiaotong' } }
   }
    
    render() {
        return <div>
             {/* 使用Provider组件提供数据 */}
            <MyContext.Provider value= {this.state.user }>
                <NavBar />
            </MyContext.Provider>
        </div>
   }
}
//NabBar.js
import React, { Component } from 'react'
import UserInfo from './UserInfo'
export default class NabBar extends
Component {
  render() {
    return (
      <div style= {
   
   {height:'50px',background:'#ccc',display:'flex',justifyContent:'space-around',alignItems:'center'}}>
        NabBar的内容
        <UserInfo />
        
        </div>
   )
 }
}
//UserInfo.js
import React, { Component } from 'react'
import MyContext from './MyContext'

export default class UserInfo extends
Component {
  render() {
    console.log(this.context)
    return (
      <div>你好,欢迎 {this.context.account}</div>
   )
 }
}
//设置类的contentType属性,从而获取context对象
UserInfo.contextType=MyContext

Function component subscribes to Context


 

 Context.Consumer

<MyContext.Consumer>
 {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
//ContextTest.js
render() {
        return <div>
           {/* 使用Provider组件提供数据 */}
            <MyContext.Provider value= {this.state.user }>
                <NavBar />
                <MyContext.Consumer>
                   {value=><div>
                        <h3>函数组件</h3>
                       获取到的账户:{value.account}
                        </div>}
                    
                </MyContext.Consumer>
              
            </MyContext.Provider>
            
        </div>
   }

Context update
When the value of the Provider changes, all consuming components inside it will be re-rendered.
 

//ContextTest.js
render() {
        return <div>
            <button onClick= {()=>this.setState({user:{name:"xiaotong",account:'xiaotong123'}})}>更新user</button>
           {/* 使用Provider组件提供数据 */}
            <MyContext.Provider value={this.state.user }>
                <NavBar />
                <MyContext.Consumer>
                   {value=><div>
                        <h3>函数组件</h3>
                       获取到的账户:{value.account}
                        </div>}
                    
                </MyContext.Consumer>
              
            </MyContext.Provider>
            
        </div>
   }

 Tip: Whether the consuming component is re-rendered is not controlled by shouldComponentUpdate.
Even if its parent component uses shouldComponentUpdate to stop rendering or the consuming component itself uses shouldComponentUpdate to stop rendering, it will not affect the continued updating of consuming components.
 

//NavBar.js
export default class NabBar extends
Component {
  shouldComponentUpdate(){
      //当前这个非消费组件会停止更新渲染,但是它的子组件UserInfo是Context的消费组件,还会继续更新
    return false
 }
  render() {
    console.log('navbar')
    return (
      <div style= {
   
   {height:'50px',background:'#ccc',display:'flex',justifyContent:'space-around',alignItems:'center'}}>
       NabBar的内容
        <UserInfo />
        
        </div>
   )
 }
}

//UserInfo.js
import React, { Component } from 'react'
import MyContext from './MyContext'
export default class UserInfo extends
Component {
    shouldComponentUpdate() {
        //虽然返回了false,但是context的值发生变化了,我还是要重新渲染的
        return false
   }
    render() {
        return (
            <div>你好,欢迎{this.context.account}</div>
       )
   }
}
UserInfo.contextType = MyContext

Fragments

 scene one:

render() {
    return (
      <p></p>
      <p></p>
   )
 }

Tip: In react, the component interface can only have one root tag.

 Scene two:

render() {
    return (
        // 最外层的这个div可能根本不需要,不想让它渲染到页面上
        <div>
             <p></p><p></p>
        </div>
    
   )
 }

Fragments allow you to wrap child elements together without adding extra nodes to the DOM.
 

render() {
    return (
   <React.Fragment>
      <p></p>
      <p></p>
   </React.Fragment>
   )
 }

Final page rendering result:

1. Fragments short syntax

使用 <></> 代替 <React.Fragment></React.Fragment>

render() {
    return (
   <>
      <p></p>
      <p></p>
   </>
   )
 }

Tip:
Because Fragments will not be rendered into DOM in the end, do not bind events or set some other attributes on Framents. Currently, only setting the key attribute is supported.

 Error Boundary_Concept

 Usually an error in one component will cause the entire application to crash and the page to go blank.

//App.js
render() {
    return (
      <>
        <ContextTest />
        <SomethingWrong />
      </>
   )
 }

//SomethingWrong.js
export default class SomethingWrong extends
Component {
  constructor(){
     // 未调用super,则会抛出错误
 }  
  render() {
    return (
      <div>
        <Child/>
      </div>
   )
 }
}

If we want components that do not have errors to continue rendering, we can use error boundaries .
ErrorBounds is a React component.
Error Bounds can catch and print JavaScript errors that occur anywhere in its subcomponent tree, and it can render out an alternate UI.
Error Bounds Catch errors during rendering, in lifecycle methods, and in constructors throughout the subcomponent tree.

 Tip: Error boundaries cannot capture errors generated in the following scenarios:
1. Event processing
2. Asynchronous code (such as setTimeout or requestAnimationFrame callback function)

3. Errors thrown by itself (not its subcomponents)

 Error Boundary_Application

1. Define an error boundary component
class. When either (or both) of the two life cycle methods static getDerivedStateFromError() or componentDidCatch() is defined in a component, the component becomes an error boundary component.

import React, { Component } from 'react'
export default class ErrorBoundary extends
Component {
    constructor() {
        super()
        this.state = { }
   }
    componentDidCatch(error, errorInfo) {
        // 捕获到子组件树当中发生的错误时调用
        this.setState({
          error: error,
          errorInfo: errorInfo
       })
        
     }
    render() {
        return (
           this.state.errorInfo ? <div>奥,糟糕!!发生了一些错误:
               错误信息如下:<br />
               {this.state.error && this.state.error.toString()}
            <br />
           {this.state.errorInfo.componentStack}
              
            </div> : this.props.children
       )
   }
}

Use of error boundaries
 

//App.js
render() {
    return (
      <>
        <ContextTest />
         {/* 使用错误边界组件包裹的组件树,发生的错误都会被这个错误边界捕获 */}
        <ErrorBoundary>
          <SomethingWrong />
        </ErrorBoundary>
      </>
   )
 }

Errors that cannot be caught by error bounds


 

 Errors that cannot be captured by error boundaries, such as event processing and asynchronous operations. You can use some methods supported by native js to capture.

 try/catch

onClick=()=>{
    try{
        //使用一个未定义的变量a,会报错
       console.log(a)
   }catch(e){
        console.log(e)
        this.setState({hasError:true})
   }
    
 }
  render() {
    return (
      <div>
        <button onClick={this.onClick}>点击</button>
       {this.state.hasError?<div>出现错误了</div>:null}
      </div>
   )
 }

window.onerror

window.onerror can capture syntax errors and runtime errors. As long as there is an error in the JS script executed in the current window, it will be captured.
 

window.onerror=function(err){
  console.log(err)
}

Refs & DOM

 Refs provide a way to access DOM elements.

<div ref={ref}></div>

Create Refs
are created using React.createRef().
Refs are usually assigned to instance properties so that they can be referenced throughout the component.
 

constructor(props) {
    super(props);
    this.myRef = React.createRef();
 }

Using Refs to set the ref
attribute to the corresponding React element is equivalent to using ref to store references to DOM nodes.
 

render() {
    return <input ref={this.myRef} />;
 }

Accessing Refs
When a ref is passed to an element in render , a reference to that node can be accessed in the ref 's current property.
 

componentDidMount(){
    const node = this.myRef.current;
    node.focus()
 }

Tip:
React will pass the DOM element to the current property when the component is mounted, and pass in the null value when the component is unmounted.

The ref will be updated before the componentDidMount or componentDidUpdate
life cycle hook is triggered.

Guess you like

Origin blog.csdn.net/m0_58719994/article/details/133162794