发布时间:2023-10-12 16:00
前言
博主主页👉🏻蜡笔雏田学代码
专栏链接👉🏻React专栏
今天来学习React的一些扩展知识
下一篇文章也会再介绍另外一些React扩展知识
感兴趣的小伙伴一起来看看吧~🤞
1️⃣ setState(stateChange, [callback])------对象式的setState
add = () => {
// 1.获取原来的count值
const { count } = this.state
// 2.更新状态
this.setState({ count: count + 1 })
console.log('12行的输出', this.state.count)
}
由于setState()是同步的方法, 但是是
异步执行
的,所以会先打印clg,再更新状态。
状态更新完毕
、界面也更新
后(render调用后)才被调用add = () => {
// 1.获取原来的count值
const { count } = this.state
// 2.更新状态
this.setState({ count: count + 1 }, () => {
console.log(this.state.count)
})
}
2️⃣ setState(updater, [callback])------函数式的setState
this.setState((state, props) => {
console.log(state, props)
return { count: state.count + 1 }
})
1️⃣对象式的setState是函数式的setState的简写方式(语法糖)
2️⃣使用原则:
- 如果新状态不依赖于原状态 ===> 使用对象方式
- 如果新状态依赖于原状态 ===> 使用函数方式
- 如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取
1️⃣引入lazy函数和Suspense组件
import React, { Component, lazy, Suspense } from 'react';
实现路由的懒加载
2️⃣通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包
const Home = lazy(() =>
import('./Home')
)
const About = lazy(() =>
import('./About')
)
3️⃣通过指定在加载得到路由打包文件前显示一个自定义loading界面
<Suspense fallback={<h1>Loading...</h1>}>
{/* 注册路由 */}
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
</Suspense>
上两篇文章着重讲解了React Hooks基础和React Hooks进阶,在此简单概括一下:
Hook是React 16.8.0版本增加的新特性/新语法
可以让你在函数组件中使用 state 以及其他的 React 特性
State Hook: React.useState()
Effect Hook: React.useEffect()
Ref Hook: React.useRef()
State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
语法:
const [xxx, setXxx] = React.useState(initValue初始值)
🔥useState()说明:
1️⃣参数: 第一次初始化指定的值在内部作缓存
2️⃣返回值: 包含
2个元素
的数组
, 第1个为内部当前状态值
, 第2个为更新状态值的函数(方法)
🔥setXxx()2种写法:
1️⃣setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
2️⃣setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
function Demo() {
// 返回值第1个为内部当前状态值, 第2个为更新状态值的函数(方法)
const [count, setCount] = React.useState(0)
const [name, setName] = React.useState('tom')
// 加的回调
function add() {
// setCount(count + 1) //第一种写法
setCount((count) => { //第二种写法
return count + 1
})
}
function change() {
setName('jack')
}
return (
<div>
<h2>当前求和为:{count}</h2>
<h2>我的名字是:{name}</h2>
<button onClick={add}>点我加1</button>
<button onClick={change}>点我改名</button>
</div>
)
}
Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
🔥React中的副作用操作:
1️⃣发ajax请求数据获取
2️⃣设置订阅 / 启动定时器
3️⃣手动更改真实DOM
🔥语法和说明:
useEffect(() => { // 在此可以执行任何带副作用操作 return () => { // 在组件卸载前执行 // 在此做一些收尾工作, 比如清除定时器/取消订阅等 } }, [stateValue])
🔥可以把 useEffect Hook 看做如下三个函数的组合:
componentDidMount() componentDidUpdate() componentWillUnmount()
React.useEffect(() => {
let timer = setInterval(() => {
setCount(count => count + 1)
}, 1000)
return () => {
//这个返回的函数相当于componentWillUnmount()
clearInterval(timer)
}
//如果不写数组,会监测任何改变(相当于componentDidMount()和componentDidUpdate())
}, [])// 如果指定的是[], 回调函数只会在第一次render()后执行(相当于componentDidMount())
1️⃣Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
2️⃣语法:
const refContainer = React.useRef()
3️⃣作用: 保存标签对象,功能与React.createRef()一样
可以不用必须有一个真实的DOM根标签了
Demo组件:
import React, { Component, Fragment } from 'react'
export default class Demo extends Component {
render() {
return (
//Fragment只能拥有key属性
<Fragment key={1}>
<input type="text" />
</Fragment>
//这种写法也行,但是这种写法不能写key等属性
//<>
//<input type="text" />
//</>
)
}
}
App.jsx:
import React, { Component, Fragment } from 'react'
import Demo from './components/5_Fragment'
export default class App extends Component {
render() {
return (
<Fragment>
<Demo />
</Fragment>
)
}
}
一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信
1️⃣创建Context容器对象:
const XxxContext = React.createContext()
2️⃣渲染子组件时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
<XxxContext.Provider value={数据}>
子组件
</XxxContext.Provider>
3️⃣后代组件读取数据:
//第一种方式:仅适用于类组件
static contextType = XxxContext // 声明接收context
this.context // 读取context中的value数据
//第二种方式: 函数组件与类组件都可以
<XxxContext.Consumer>
{
value => ( // value就是context中的value数据
要显示的内容
)
}
</XxxContext.Consumer>
祖组件A想要给孙组件C传递数据: 用户名和年龄
import React, { Component } from 'react'
import './index.css'
// 创建Context对象
const MyContext = React.createContext()
export default class A extends Component {
state = { username: 'tom', age: 18 }
render() {
const { username, age } = this.state
return (
<div className='parent'>
<h3>我是A组件</h3>
<h4>我的用户名是:{username}</h4>
<MyContext.Provider value={{ username, age }}>
<B />
</MyContext.Provider>
</div>
)
}
}
class B extends Component {
render() {
return (
<div className='child'>
<h3>我是B组件</h3>
<C />
</div>
)
}
}
//孙组件为类组件
class C extends Component {
// 声明接收context
static contextType = MyContext
render() {
// 打印出后代组件的this显示出后代组件的context
console.log(this.context)
return (
<div className='grand'>
<h3>我是C组件</h3>
<h4>我从A组件接收到的用户名是:{this.context.username},年龄是:{this.context.age}</h4>
</div>
)
}
}
//孙组件为函数组件
function C() {
return (
<div className='grand'>
<h3>我是C组件</h3>
<h4>我从A组件接收到的用户名是:
<MyContext.Consumer>
{
value => {
return `${value.username},年龄是${value.age}`
}
}
</MyContext.Consumer>
</h4>
</div>
)
}
在应用开发中一般不用context, 一般都用它封装react插件, react-redux库底层使用了context.
今天的分享就到这里啦✨ \\textcolor{red}{今天的分享就到这里啦✨} 今天的分享就到这里啦✨
原创不易,还希望各位大佬支持一下 \\textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
🤞 点赞,你的认可是我创作的动力! \\textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \\textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \\textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!