官方文档:React.Component – React
(1)stateChange 为状态改变对象 ( 该对象可以体现出状态的更改 )。
(2)callback 是可选的回调函数,它在状态更新完毕、界面也更新后 ( render 调用后 ) 才被调用。
// 1. 对象式写法
const { count } = this.state
this.setState({ count: count + 1 }, () => {
console.log('对象式写法:', this.state.count);
})
(1)updater 为返回 stateChange 对象的函数。
(2)updater 可以接收到 state 和 props。
(3)callback 是可选的回调函数,它在状态更新、界面也更新后 ( render调用后 ) 才被调用。
// 2. 函数式写法
this.setState(
(state, props) => {
return { count: state.count + 1 }
},
() => { console.log('函数式写法:', this.state.count); })
总结:
(1)对象式的 setState 是函数式的 setState 的简写方式 ( 语法糖 )。
(2)使用原则:(也不一定按照这个,看自己方便选叭)
① 如果新状态不依赖于原状态 ===> 使用对象方式
② 如果新状态依赖于原状态 ===> 使用函数方式
③ 如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中读取。
说明:React.lazy
函数能让你像渲染常规组件一样处理动态引入(的组件)。
(就是比如有100个组件,你只打开了3个,默认情况下是页面直接加载了100个组件,加了 lazy 函数之后只加载用到的组件)
官方文档:代码分割 – React
// 导入模块
import React, { Component, lazy, Suspense} from 'react'
// loading 为兜底的模块,假设网速比较慢,组件还未出来时加载 loading 组件
import Loading from './Loading'
//通过 React 的 lazy 函数配合 import() 函数动态加载路由组件 ===> 路由组件代码会被分开打包
const Home = lazy(()=> import('./Home') )
const About = lazy(()=> import('./About'))
// 通过 指定在加载得到路由打包文件前显示一个自定义 loading 界面
}>
{/* 注册路由 */}
官方文档:Hook 概览 – React
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
React Hook / Hooks 是什么?
(1)Hook是React 16.8.0版本增加的新特性 / 新语法。
(2)可以让你在函数组件中使用 state 以及其他的 React 特性。
三个常用的 Hook:
(1)State Hook:React.useState()。
(2)Effect Hook:React.useEffect()。
(3)Ref Hook:React.useRef()。
(1)State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作。
(2)语法:const [xxx, setXxx] = React.useState(initValue) 。
(3)useState() 说明:
参数:第一次初始化指定的值在内部作缓存。
返回值:包含2个元素的数组,第1个为内部当前状态值,第2个为更新状态值的函数。
(4)setXxx() 2种写法:
setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值。
setXxx(value => newValue):参数为函数,接收原本的状态值,返回新的状态值,内部用其覆盖原来的状态值。
import React from 'react'
export default function App() {
// const [状态, 更新状态的方法] = React.useState(initValue)
const [count, setCount] = React.useState(0);
function add() {
setCount(count + 1);
}
return (
此组件的和为:{count}
)
}
(1)Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)。
(2)React中的副作用操作:
① 发ajax请求数据获取。
② 设置订阅 / 启动定时器。
③ 手动更改真实DOM。
(3)语法和说明:
useEffect(() => { // 在此可以执行任何带副作用操作 return () => { // 在组件卸载前执行 // 在此做一些收尾工作, 比如清除定时器/取消订阅等 } }, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
(4)可以把 useEffect Hook 看做如下三个函数的组合:
componentDidMount()
componentDidUpdate()
componentWillUnmount()
import React from 'react'
import { root } from '.';
export default function App() {
// const [状态, 更新状态的方法] = React.useState(initValue)
const [count, setCount] = React.useState(0);
function add() {
setCount(count + 1);
}
function unmountNode() {
root.unmount()
}
React.useEffect(() => {
const timer = setInterval(() => {
// 这里设置的是刷新页面后 count 定时自增 1
setCount(count => count + 1);
}, 500);
return () => {
// 相当于 componentWillUnmount()
// 清除定时器
clearInterval(timer);
}
}, []);
// 如果第二个参数为 [], 则相当于 componentDidMount()
// 如果第二个参数有具体的值 [count], 则相当于 componentDidUpdate(), 会监测数据的更新
return (
此组件的和为:{count}
)
}
(1)Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据。
(2)语法:const refContainer = useRef()。
(3)作用:保存标签对象,功能与React.createRef()一样。
import React from 'react'
export default function App() {
const ref = React.useRef();
function show() {
console.log(ref.current.value);
}
return (
)
}
官方文档:Fragments – React
React 中的一个常见模式是一个组件返回多个元素。Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
render() {
return (
);
}
官方文档:Context – React
一种组件间通信方式,常用于【祖组件】与【后代组件】间通信。
(1) 创建 Context 容器对象。
const XxxContext = React.createContext()
(2)渲染子组时,外面包裹 xxxContext.Provider,通过value属性给后代组件传递数据。
子组件
(3)后代组件读取数据。
//第一种方式:仅适用于类组件
static contextType = xxxContext // 声明接收context
this.context // 读取context中的value数据
//第二种方式: 函数组件与类组件都可以
{
value => ( // value就是context中的value数据
要显示的内容
)
}
(1)只要执行 setState(),即使不改变状态数据,组件也会重新render()。
(2)只当前组件重新 render(),就会自动重新 render 子组件 ==> 效率低。
(3)原因:Component 中的 shouldComponentUpdate() 总是返回 true。
(4)效率高的做法:只有当组件的 state 或 props 数据发生改变时才重新 render()。
比较新旧 state 或 props 数据,如果有变化才返回 true,如果没有返回 false。
shouldComponentUpdate(nextProps,nextState){
console.log(this.props,this.state); // 目前的props和state
console.log(nextProps,nextState); // 接下要变化的目标props,目标state
return !this.state.carName === nextState.carName
}
官方文档:React 顶层 API – React
PureComponent 重写了 shouldComponentUpdate(),只有 state 或 props 数据有变化才返回 true。
// 导入 PureComponent 就行
import React, { PureComponent } from 'react'
官方文档:Render Props – React
如何向组件内部动态传入带内容的结构(标签)?
(1)使用 children props:通过组件标签体传入结构。
(2)使用render props:通过组件标签属性传入结构,一般用 render 函数属性。
children props:
xxxx {this.props.children}
问题:如果 B 组件需要 A 组件内的数据 ==> 做不到
render props:
A组件:{this.props.render(内部state数据)}
C组件:读取A组件传入的数据显示 {this.props.data}
官方文档:错误边界 – React
理解:用来捕获后代组件错误,渲染出备用页面。
特点:只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误。
使用方式:getDerivedStateFromError 配合 componentDidCatch
// 生命周期函数,一旦后台组件报错,就会触发 static getDerivedStateFromError(error) { console.log(error); // 在render之前触发 // 返回新的state return { hasError: true, }; } componentDidCatch(error, info) { // 统计页面的错误。发送请求发送到后台去 console.log(error, info); }
(1)props:① children props。② render props。
(2)消息订阅-发布:pubs-sub、event 等等。
(3)集中式管理:redux、dva 等等。
(4)conText:生产者-消费者模式。
(1)父子组件:props。
(2)兄弟组件(非嵌套组件):消息订阅-发布、集中式管理。
(3)祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(用的少)。