- userContext()
- userReducer()
- useMemo()
- useCallback()
4. userContext
- userContext的作用
userContext就是context的接收方式不同,在前边的react传值梳理中我们就已经说过,有一种方式就是context传值,context在react中就如字面含义一样,是我们react使用中的一种容器,通过React.createContext来创建一个容器ContextObj
,容器作为标签ContextObj.Provider
包裹我们要传递值的生产者,那我们内部的所有消费者,也就是子组件,都可以通过ContextObj.Consumer
来包裹,然后通过箭头函数的模式获取到参数value,内部也都可以正常使用整个value的值,但是无疑这种方法是繁琐的,那么我们函数式组件中的跨级传输救星来了,就是userContext
,userContext
可以直接获取到我们所需的值,让消费者解放出来,不再需要标签包裹就能获取到相应的参数 - userContext使用
import React,{ useContext } from 'react'
const Ceshi = () => {
const AppContext = React.createContext({})
const A =() => {
const { name } = useContext(AppContext)
return (
<p>我是A组件的名字{name}<span>我是A的子组件{name}</span></p>
)
}
const B =() => {
const { name } = useContext(AppContext)
return (
<p>我是B组件的名字{name}</p>
)
}
return (
<AppContext.Provider value={{name: 'hook测试'}}>
<A/>
<B/>
</AppContext.Provider>
)
}
export default Ceshi
5. userReducer
-
userReducer的作用
我们之前梳理的rudex我们可以看一下,我们也可以在这里简单说一下,redux是react的一种状态共享方式,内部有一个很重要的概念就是reducer,reducer就是作为我们action,也就是通知处理方案的函数,这个函数会接收到两个值,一个是state,也就是旧时的状态,另一个就是我们的action通知,且可以拿到我们的dispatch通知时候传递过来的type和传递的value,这两个值一个可以让我们做出判断走哪里的修改逻辑,另一个可以让我们获取到要修改替换的属性的新值,从而达到对旧值更改的目的,当然了我们的userReducer也是从rudex中吸取的经验所产生的,只不过userReducer是直接可以在hooks中进行使用的,不用引入新的rudex和rudex-react,内置hooks -
userReducer的使用
import React,{useReducer} from 'react'
const AddCount = () => {
const reducer = (state, action) => {
if(action.type === 'add'){
return {
...state,
count: state.count +1,
}
}else {
return state
}
}
const addcount = () => {
dispatch({
type: 'add'
})
}
const [state, dispatch] = useReducer(reducer, {count: 0})
return (
<>
<p>{state.count}</p>
<button onClick={addcount}>count++</button>
</>
)
}
export default AddCount
- 与useContext配合使用
import React from 'react';
import './style.css';
//createContext函数内可以传递一个默认的共享数据,我们用不到所以传
const ContextObj = React.createContext();
function AAA() {
const { dispatch} = useContext(AppContext)
return (
<div>
我是组件1我除了自己的逻辑,我还可以更改组件2获取的值
<button
onClick={() => {
dispatch({
type: 'change',
name: 333
})
}}
>
点击改变值
</button>
</div>
);
}
function BBB() {
const { name } = useContext(AppContext)
return (
<div>我是组件2获取到的值:{name}</div>
);
}
function App() {
const AppContext = React.createContext({})
const reducer = (state, action) => {
if(action.type === 'change'){
return {
...state,
name: action.name,
}
}else {
return state
}
}
const [state, dispatch] = useReducer(reducer, {name: 222})
return (
<ContextObj.Provider
value={{name, dispatch}}
>
<div>
<AAA />
<BBB />
</div>
</ContextObj.Provider>
);
}
export default App;
6. useMemo
我们都知道react是自动进行更新且会自动更新所有的子组件的,我们的useMemo需要我们从头说起,从最开始的缓存说起
PureComponent
我们之前没有说过这个,这次趁机说一下这个PureComponent,这个的用法就是在我们进行类组件的创建的时候,不再从react.Component来继承,而是从PureComponent来继承,如此一来我们的类组件会自动多一个方法,就是每次更新的时候把props和state做一次浅比较,看一看我们使用的组件需不需要做出更新,当然了我们之前也说过,用shouldComponentUpdate可以自定义比较方法,根据我们自定义的比较返回true或者false来表明是否需要更新render,但是如果我们用PureComponent就可以自己进行浅比较
import React, { PureComponent } from 'react';
class IndexPage extends PureComponent{
constructor() {
super();
this.state = {
isShow: 1
};
}
render() {
return (
<div>
<div>{this.state.isShow}</div>
</div>
);
}
}
React.memo
react的HOC(高阶组件),我们可以通过这个高阶组件进行缓存的处理,每次我们的父组件更新的时候,用这个高阶组件包装导出的组件都会进行对比方法的调用,当然了对比方法就是我们在进行高阶组件包装时候传入的方法,且注意,react.memo就是为了我们的函数式组件的缓存出现的,所以我们函数式组件很适合用这个高阶组件
import React, { memo } from 'react';
function MyComponent(props) {
return <div>{props.name}<div>
}
function areEqual(prevProps, nextProps) {
//做旧props和新props的对比
}
export default memo(MyComponent, areEqual);
useMemo
useMemo为我们提供的是更加简便的用法以及更加只能的监控数据是否改变,我们可以把我们依赖的值细分且传入useMemo包裹之后的组件中的第二个数组参数中,这样useMemo就会替我们做对比,来判断是否要更新组件,依赖的传入方式使我们开发更加的顺畅,不用每次都写那么多的比较逻辑,重复且复杂
import React, { useMemo } from 'react';
function MyComponent(props) {
return useMemo(() => {
return <div>
<p>number is : {props.number}</p>
</div>
}, [props.number]);
}
export default MyComponent;
7. useCallback
- useCallback的作用
useCallback与上边讲的几个缓存的方式不同,useCallback做的是函数的缓存,为什么要做函数的缓存,要知道我们在整个函数组件中,不管任何东西做出改变,整个的函数一定意义上是要重新走一遍的,也就意味着我们的函数每次都是进行了一次重新定义,js中的对象,进行两次完全一样的创建,进行全等对比,都是不相等的,为什么,因为对象是引用变量,那么我们就知道函数也是引用变量,每次传递给子组件的函数都是作用一样,但是引用是不一样的,这就会导致我们传递的参数实际上是在每次父组件更新时都在发生改变的,我们就可以对函数进行缓存,这样每次组件刷新生成的函数都是同一个引用,传递的时候子组件接收到的也就是同一个函数了
import React, { memo, useCallback, useState } from 'react'
function PageA (props) {
const { onClick, children } = props
return <div onClick={onClick}>{children}</div>
}
function PageB ({ onClick, name }) {
return <div onClick={onClick}>{name}</div>
}
const PageC = memo(PageB)
function UseCallback() {
const [a, setA] = useState(0)
const [b, setB] = useState(0)
const handleClick1 = () => {
setA(a + 1)
}
const handleClick2 = useCallback(() => {
setB(b + 1)
}, [b])
return (
<>
<PageA onClick={handleClick1}>{a}</PageA>
<PageC onClick={handleClick2} name={b} />
</>
)
}
export default UseCallback