react拓展

setState()

setState更新状态的2种方式

  1. 对象式的setState
setState(stateChange,[callback])

1. stateChange为状态改变对象
2. callback是可选的回调函数,它在状态更新完毕,界面也更新后(render调用后)才被调用
  1. 函数式的setState
setState(updater, [callback])
1. updater为返回stateChange对象的函数
2. updater可以接收到state和props
3. callback是可选的回调函数,它在状态更新、界面更新后(render调用后)才被调用

state = { count: 0 }

add = () => {
  // 对象式的setState
  const { count } = this.state // 0
  this.setState({ count: count + 1}, () => {
    console.log(this.state.count) // 1
  })
    console.log(this.state.count) // 0
  
  // 函数式编程
  /*
  this.setState((state,props) => {
    return {
      count: state.count + 1
    } 
  })
  **/
  this.setState(state => ({count: state.count + 1}))
  
}

对象式的setState是函数式的setState的简写方式

使用原则:

1.如果新状态不依赖于原状态 ====> 使用对象方式

2.如果新状态依赖于原状态 =====> 使用函数方式

3.如果需要在setState()执行后获取最新的状态数据,需要在第二个callback函数中读取

lazyLoad

路由组件的lazyLoad

import React, { Component, lazy, Suspense } from 'react'

const Loading from './Loading'
const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))


}>
  {/* 注册组件 */}
    
  



Hooks

React Hook/Hooks是什么?

  1. Hook是React 16.8.0版本增加的新特性/语法
  2. 可以使在函数组件中使用state以及其他的React特性

三个常用的Hook

  1. State Hook:React.useState()

    1. State Hook 让函数组件也可以有state状态,并进行状态数据的读写操作

    2. 语法:const [xxx, setXxx] = React.useState(initValue)

    3. useState()说明

      1. 参数:第一次初始化制定的值在内部做换粗
      2. 返回值:包含2个元素的数组,第一个为内部值当前状态值,第二个为更新状态值的函数
    4. setXxx()的2种写法:

      1. setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的值
      2. setXxx(value => newValue):参数作为函数,接受原本的状态值,返回新的状态值,内部用其覆盖原来的状态值
    5. function Test () {
          console.log('Test组件')
          const [count, setCount] = React.useState(0)
          const [name, setName] = React.useState('tom')
          function add () {
              // setCount(count + 1) // 第一种写法
              setCount(count => count + 1)
          }
          function changeName() {
              setName('jack')
          }
          return(
              

      Hooks

      当前数值为{ count }

      我的名字是:{ name }

      ) } export default Test
  2. Effect Hook:React.useEffect()

    1. Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)

    2. React中的副作用操作

      1. 发送ajax操作
      2. 设置订阅/启动定时器
      3. 手动更改真实DOM
    3. 语法说明:

      1. useEffect(() => {
           // 在此可以执行任何带副作用的操作
          return () => {
            // 在此做一些收尾工作,比如:清除定时器/取消订阅等
          }
        },[stateValue]) // 如果制定的是[],回调函数只会在第一次render()后执行
        
      2. 可以把 useEffect Hook 看做如下三个函数的组合

        1. componentDidMount()
          componentDidUpdate()
          componentWillUnmount()
          
      3. function Test () {
            console.log('Test组件')
            const [count, setCount] = React.useState(0)
            React.useEffect(() => {
                let timer = setInterval(() => {
                    setCount(count => count + 1)
                }, 1000);
                return () => {
                    console.log('卸载组件####')
                    clearInterval(timer)
                }
            },[])
            function unMount() {
                reactDom.unmountComponentAtNode(document.getElementById('root'))
            }
            return(
                

        Hooks

        当前求和为{ count }

        ) }
  3. Ref Hook

    1. Ref Hook 可以在函数组件中存储/查找组件内的标签或任意其他数据
    2. 语法:const refContainer = React.useRef()
    3. 作用:保存标签对象,功能与React.createRef() 一样
function Test () {
    const refContainer = React.useRef()
    function show() {
        alert(refContainer.current.value)
    }
    return(
        
) }

Fragment

可以不用必须有一个真实DOM根标签了


        
    


// 编译后


Context

一种组件间通信方式,常用于[祖组件]与[后代组件]间通信,一般都用于封装react插件

使用:

import React, { Component } from 'react'

// 创建一个Context对象
const MyContext = React.createContext()
const { Provider, Consumer } = MyContext
export default class ContextComponent extends Component {
    state = { userName: '张三', age: 18 }
    render() {
        const { userName, age } = this.state
        return (
            

Context

) } } class A extends Component { render() { return(

我是a组件

) } } class B extends Component { state = { userName: 'tom' } render() { return(

我是B组件

) } } // 类式组件 class C1 extends Component { // 声明context static contextType = MyContext state = { userName: 'tom' } render() { return(
我是C1组件
Context接收到的用户名:{ this.context.userName }, 年龄:{ this.context.age }
) } } // 函数组件、类式组件都可以 function C2 () { return(
我是C2组件
Context接收到的 {/* value 就是 context 中的 value 数据 */} { value => `用户名:${ value.userName },年龄:${ value.age }` }
) }

组件优化

component的2个问题

  1. 只要执行setState(),即使不改变状态数据,组件也会重新render()
  2. 当前组件重新render(),会自动重新render()子组件,即使没使用父组件的任何数据 ===> 效率低

效率高的做法

只有当组件的state或props数据发生改变时才重新render()

原因

component中的shouldComponentUpdate()总是返回true

  1. 解决一:重写shouldComponentUpdate()方法,比较新旧state或props数据,如果有变化才返回true,如果没有返回false
export default class Car extends Component {
    state = { carName: '奔驰63' }
    changeCar = () => {
        this.setState({
            carName: '迈巴赫'
        })
    }
    shouldComponentUpdate(nextProps, nextState) {
        console.log(this.props, this.state) // 当前props和state
        console.log(nextProps, nextState) // 接下来要变化的props和state
        return !this.state.carName === nextState.carName
    }
    render() {
        console.log('Car-parent render')
        const { carName } = this.state
        return (
            

我是Parent组件

我的车名字时:{carName}

) } } class Child extends Component { render() { console.log('Car-child render') const { carName } = this.props return (

我是Child组件

我接到的车是:{ carName }

) } }
  1. 解决二:使用PureComponent,PureComponent重写了shouldComponentUpdate(),只有state或props数据有变化才返回true
import React, { PureComponent } from 'react'

export default class Car extends PureComponent {
    state = { carName: '奔驰63' }
    changeCar = () => {
        this.setState({
            carName: '迈巴赫'
        })
    }
    render() {
        console.log('Car-parent render')
        const { carName } = this.state
        return (
            

我是Parent组件

我的车名字时:{carName}

) } } class Child extends PureComponent { render() { console.log('Car-child render') const { carName } = this.props return (

我是Child组件

我接到的车是:{ carName }

) } }

注意⚠️: 只是进行state和props数据的浅比较,如果只是数据对象内部数据变了,返回false。不能直接修改state数据,而是要产生新数据。项目中一般使用PureComponent来优化

render props

  1. children props:通过组件标签体传入结构

    1. 
        
      
      
      { this.props.children } // 如果B组件需要A组件内的数据  ===> 做不到
      
  2. Render props:通过组件标签属性传入结构,一般使用render函数属性

    1.  }>
      // A 组件
      { this.props.render(内部state数据) }
      // C 组件 --- 读取A组件传入的数据显示
      { this.props.data }
      
      

Error boundary

错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面

只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误

使用方式

static getDerivedStateFromError(error){
  console.log(error)
  return {
    hasError: true
  }
}

componentDidCatch(error, info) {
  // 统计页面的错误,发送请求到服务端
  console.log(error, info)
}

你可能感兴趣的:(react拓展)