react扩展
1. setState
setState 更新状态的2种写法
- setstate(statechange[, callback])--对象式的 setState
1.statechange 为状态改变对象(该对象可以体现出状态的更改)
2.callback 是可选的回调函数,它在状态更新完毕、界面也更新(render 调用后)才被调用 - setstate(updater[, callback])--函数式的 setState
1.updater 为返回 stateChange 对象的函数。
2.updater 可以接收到 state 和 props。
3.callback是可选的回调函数,它在状态更新、界面也更新后(render调用后)才被调用。
总结:
1.对象式的setState是函数式的setState的简写方式(语法糖)
2.使用原则:
(1).如果新状态不依赖于原状态 -> 使用对象方式
(2).如果新状态依赖于原状态 -> 使用函数方式
(3).如果需要在setState() 执行后获取最新的状态数据,要在第二个callback函数中读取
2. lazyLoad
路由组件的lazyLoad
//1.通过React的lazy函数配合import()函数动态加载路由组件,路由组件代码会被分开打包
const Login = lazy(() => import('@/pages/Login'))
//2.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义1oading界面
<Suspense fallback={<h1>1oading. .</h1>]}>
<Switch>
<Route path="/xxx" component={Xxxx}/>
<Redirect to="/login"/>
</Switch>
</Suspense>
3. Hooks
1. React Hook/Hooks 是什么?
- Hook 是 React16.8.0 版本增加的新特性/新语法
- 可以让你在函数组件中使用 state 以及其他的 React 特性
2.三个常用的 Hook
- State Hook: React.useState()
- Effect Hook: React.useEffect()
- Ref Hook: React.useRef()
3.State Hook
- State Hook 让函数组件也可以有 state 状态,并进行状态数据的读写操作
- 语法:
const [xxx,setxxx] = React.usestate(initvalue)
- useState() 说明:
参数:第一次初始化指定的值在内部作缓存
返回值:包含2个元素的数组,第1个为内部当前状态值,第2个为更新状态值的函数 - setXxx() 两种写法:
setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值
setxxx(value =>newValue):参数为函数,接收原本的状态值,返回新的状态值,内部用其覆盖原来的状态值
4.Effect Hook
- Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
- React中的副作用操作:
发 ajax 请求数据获取
设置订阅/启动定时器
手动更改真实 DOM - 语法和说明:
useEffect(()=>{ //在此可以执行任何带副作用操作 return()=>{//在组件卸载前执行 //在此做一些收尾工作,比如清除定时器/取消订阅等 } },[stateValue])//如果指定的是[],回调函数只会在第一次render()后执行
- 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount() componentDidUpdate() componentWillUnmount()
5. useLayoutEffect()
useLayoutEffect 是 useEffect 的一个版本,在浏览器重新绘制屏幕之前触发。
6. Ref Hook
- Ref Hook 可以在函数组件中存储/查找组件内的标签或任意其它数据
- 语法:
const refcontainer = useRef()
- 作用:保存标签对象,功能与
React.createRef()
一样
7. useMemo()
useMemo 它使用来做缓存用的,只有当一个依赖项改变的时候才会发生变化,否则拿缓存的值,就不用在每次渲染的时候再做计算
import { useMemo } from 'react';
const getNumMemo = useMemo(() => {
return count * 10
}, [count])
8. memo()
在 react 的一般规则中,只有父组件的某一个状态改变,父组件下面所有的子组件不论是否使用了该状态,都会进行重新渲染。显然,对于没有用到被改变的那个状态的组件来说,重新渲染是完全没有必要的。所以,React.memo 就诞生了。
import { memo } from 'react';
const Child = () => {}
export default memo(Child)
9. useCallback()
- useCallBack 的本质工作不是在依赖不变的情况下阻止函数创建,而是在依赖不变的情况下不返回新的函数地址而返回旧的函数地址。不论是否使用 useCallBack 都无法阻止组件 render 时函数的重新创建!!
- 在往子组件传入了一个函数并且子组件被 React.memo 缓存了的时候使用
import { useCallback } from 'react';
const updateCount = useCallback(() => console.log('父业务'), [])
return(
<Child updateCount={updateCount}></Child>
)
4. Fragment 使用
//作用:可以不用必须有一个真实的DOM根标签了
<Fragment key="xxx"><Fragment>
<></>
5.Context
理解
一种组件间通信方式,常用于【祖组件】与【后代组件】间通信
使用
- 创建 Context 容器对象:
const XxxContext = React.createContext()
- 渲染子组件时,外面包裹 xxxContext.Provider,通过 value 属性给后代组件传递数据:
<XxxContext.Provider value={数据}> 子组件 </XxxContext.Provider>
- 后代组件读取数据:
//第一种方式:仅适用于类组件 static contextType = XxxContext //声明接收context this.context //读取context中的value数据 //第二种方式:函数组件与类组件都可以 <XxxContext.Consumer> { value => (//value就是context中的value数据 要显示的内容 ) } </XxxContext.Consumers> //第三种方式:函数组件 import { useContext } from 'react' const { count } = useContext(AppContext)
注意
在应用开发中一般不用 context,一般都用它的封装 react 插件
6.组件优化
Component 的2个问题
1.只要执行 setState(),即使不改变状态数据,组件也会重新 render()
2.只当前组件重新 render(),就会自动重新 render 子组件,即使子组件没有用到父组件的任何数据 效率低
效率高的做法
只有当组件的 state 或 props 数据发生改变时才重新 render()
原因
Component 中的 shouldComponentUpdate() 总是返回 true
解决
办法1:
重写 shouldcomponentUpdate(nextProps, nextState) 方法
比较新旧 state 或 props 数据,如果有变化才返回 true,如果没有返回 false
办法2:
使用 PureComponent
PureComponent 重写了 shouldcomponentUpdate(),只有 state 或 props 数据有变化才返回 true
注意:
只是进行 state 和 props 数据的浅比较,如果只是数据对象内部数数据变了,返回 false
不要直接修改 state 数据,而是要产生新数据
项目中一般使用 PureComponent 来优化
7.render props
如何向组件内部动态传入带内容的结构(标签)?
Vue 中:
使用 slot 技术,也就是通过组件标签体传入结构 <A><B/></A>
React中:
使用 children props:通过组件标签体传入结构
使用 render props:通过组件标签属性传入结构,而且可以携带数据,一般用 render 函数属性
children props
//父组件
<A>
<B>xxxx</B>
</A>
//子组件
{this.props.children}
问题:如果B组件需要A组件内的数据,做不到
render props
<A render={(data) => <B data={data}></B>}></A>
A组件:{this.props.render(内部state数据)}
B组件:读取A组件传入的数据显示{this.props.data}
8.错误边界
理解:
错误边界(Error bolundary):用来捕获后代组件错误,渲染出备用页面
特点:
只能捕获后代组件 生命周期 产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
使用方式:
getDerivedStateFromError 配合 componentDidCatch
//生命周期函数,一旦后台组件报错,就会触发
static getDerivedstateFromError (error){
console.1og(error);
//在render之前触发
//返回新的state
return {
hasError: error,
};
}
componentDidcatch(error, info){
//统计页面的错误。发送请求发送到后台去
console.log(error, info);
}
9.组件通信方式总结
组件间的关系:
父子组件
兄弟组件(非嵌套组件)
祖孙组件(跨级组件)
几种通信方式:
1.props:
(1).children props
(2).render props
2.消息订阅-发布:
pubs-sub、event等等
3.集中式管理:
redux、dva等等
4.Context:
生产者-消费者模式
比较好的搭配方式:
父子组件:props
兄弟组件:消息订阅-发布、集中式管理
祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(开发用的少,封装插件用的多)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析