React扩展知识 ~ setState与lazyLoad

674 阅读3分钟

React扩展知识点

setState

更新状态的两种写法:

  • 对象式: setState(stateChange, [callback])
    1. stateChange为状态改变对象(该对象可以体现出状态的更改)
    2. callback是可选的回调函数,它在状态更新完毕,并且界面渲染之后才被调用
  • 函数式: setState(updater, [callback])
    1. updater为返回stateChange对象的函数
    2. updater可以接收到state和props
    3. callback是可选的回调函数,它在状态更新完毕,并且界面渲染之后才被调用

案例演示 我们还是用之前的求和案例来做演示,基础代码如下:

import React, { Component } from 'react'

export default class SetStateDemo extends Component {

  state = {count: 0}

  render() {
    return (
      <div>
        <h1>当前求和为:{this.state.count}</h1>
        <button onClick={this.add}>点我+1</button>
      </div>
    )
  }
}

对象式 callback函数式是非必填的参数,由于setState是异步的,当我们在设置完成状态之后,如果需要使用更新后的状态做一些其他的操作,可以使用该参数,直接在当前代码块中查询状态的话,可能会查询到更新之前的状态值,例如:

// 对象式 setState
add = () => {
const {count} = this.state
this.setState({count: count + 1}, () => {
  console.log('callback: ', this.state.count)
})
console.log('验证state异步更新', this.state.count)
}

image.png

函数式 在函数式的函数中,可以拿到stateprops

// 函数式 setState
add = () => {
this.setState((state, props) => {
  return {count: state.count + 1}
})
}

小结:

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

  2. 使用原则: 1)如果新状态不依赖于原状态 --- 使用对象方式

    2)如果新状态依赖于原状态 --- 使用函数方式

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

lazyLoad

路由组件应该是使用懒加载最多的组件了,我们一个项目中有几十上百个组件都是很常见的事情,如果每次请求,都要将所有的组件加载出来,哪怕你根本就用不上,那样会严重的影响到用户的体验感的。以前面讲解过的路由组件案例为例:

import React, { Component } from 'react'
import { NavLink, Routes, Route } from 'react-router-dom'
import Home from './Home'
import About from './About'

export default class LazyLoadDemo extends Component {
    render() {
        return (
            <div id='root'>
                <div>
                    <div className='row'>
                        <div className='col-xs-offset-2 col-xs-8'>
                            <div className='page-header'>
                                <h2>React Router Demo</h2>
                            </div>
                        </div>
                    </div>
                    <div className='row'>
                        <div className='col-xs-2 col-xs-offset-2'>
                            <div className='list-group'>
                                <NavLink className='list-group-item' to='/about'>About</NavLink>
                                <NavLink className='list-group-item' to='/home'>Home</NavLink>
                            </div>
                        </div>
                        <div className='col-xs-6'>
                            <div className='panel'>
                                <div className='panel-body'>
                                    <Routes>
                                        <Route path='/about' element={<About/>}/>
                                        <Route path='/home' element={<Home/>}/>
                                    </Routes>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

当我们打开网页时,还没点击About或者是Home按钮,它就已经先帮我们将资源加载好了,如下图所示: image.png

我们点击清除按钮,再点击About按钮,可以看到没有发出任何的请求

image.png

我们需要的效果应该是,当用户点击了某个路由导航,我们才去发起请求,哪怕有一百个,一千个,用户只点击了两三个,那么发出的请求就只有两三个,而不会缓存很多用不上的。

要实现懒加载,我们需要借助react框架的lazy函数,具体使用方式如下:

  1. 引入lazy
import React, { Component, lazy } from 'react'
  1. 修改引入路由组件的方式,lazy函数的入参也是一个函数,我们在函数回调中使用import()的方式引入组件
const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))

调整好了,我们看看效果:

image.png

哦吼,报错了,错误提示的大概意思就是说,选择了懒加载,当我们网速过慢的时候,选中的路由组件还未加载出来,需要有一个兜底的组件来展示。

  1. 引入Suspense,指定一个兜底的组件,将其余的路由组件包裹起来
import React, { Component, lazy, Suspense } from 'react'
<Suspense fallback={<h1>Loading...</h1>}>
    <Routes>
        <Route path='/about' element={<About/>}/>
        <Route path='/home' element={<Home/>}/>
    </Routes>
</Suspense>

通过控制台的设置,将Online模式调整为Slow 3G模式,我们可以看到点击按钮时,由于网络延迟,它会先展示出兜底组件的信息,然后再调整到我们请求的组件。

image.png

image.png

本文正在参加「金石计划 . 瓜分6万现金大奖」