这篇文章不错 https://www.cnblogs.com/ascoders/p/10591832.html
一开始用useCallback包裹了这个函数,这个函数的handleAction中有用到一个paramsMemo的数据,这个数据是声明在外面的。这样有个问题是handleAction中拿到的paramsMemo一直是最开始的数据。
所以疑问是 useCallback中会拿不到外面变量的更新么?
我的理解:
useCallback也应该有依赖,不然其里面用到的变量会一直是最开始那个,因为每次render都有自己独立的props,state,effects,事件处理!
除了useRef,利用 useRef 就可以绕过 Capture Value 的特性。可以认为 ref 在所有 Render 过程中保持着唯一引用,因此所有对 ref 的赋值或取值,拿到的都只有一个最终状态,而不会在每个 Render 间存在隔离。
依赖不丢、逻辑内聚,从而容易维护。
所以我一开始使用了useCallback,但是没有给其传依赖,但是里面又用到了,所以就导致这样的问题。
rightControlButton
const rightControlButton =
useCallback(
(row: DataManagement.DataManagementListItem) => {
switch (row.lineStatus) {
case null:
case 1:
return (
< Button type="link" onClick={() => handlerAction(row, 'offline')} title="下线">
<BdpIcon type="iconxiaxian" color="#3954FF"></BdpIcon>
</Button>
)
case 0:
return (
<Button type="link" onClick={() => handlerAction(row, 'online')} title="启用">
<BdpIcon type="iconshangxian" color="#3954FF"></BdpIcon>
</Button>
);
case 2:
default:
// 流程中和其他的状态展示上线的图标,但是要置灰!
return (
<Button type="link" disabled>
<BdpIcon type="iconshangxian" color="#DDD"></BdpIcon>
</Button>
)
}
}
[])
paramsMemo
const paramsMemo = useMemo(() => {
const { keyword, pageNum = 1, pageSize = 10, topic, lineStatus, type = 1 } = params;
let params1: DataManagement.tepeListByManager = {
keywords: keyword ? keyword : '',
topic: topic === 'all' ? '' : topic,
lineStatus: lineStatus === 'all' ? '' : lineStatus,
pageNum: pageNum,
pageSize: pageSize,
type: currentUser.type ? currentUser.type : 1
}
return params1
}, [params])
最后 将useCallback注释掉就好了,或者在useCallback的依赖中加上paramsMemo,不过这样一来二去显得很繁琐了,目前没有找到最好的使用useMemo,useCallback的套路。
const rightControlButton =
// useCallback(
(row: DataManagement.DataManagementListItem) => {
switch (row.lineStatus) {
case null:
case 1:
return (
< Button type="link" onClick={() => handlerAction(row, 'offline')} title="下线">
<BdpIcon type="iconxiaxian" color="#3954FF"></BdpIcon>
</Button>
)
case 0:
return (
<Button type="link" onClick={() => handlerAction(row, 'online')} title="启用">
<BdpIcon type="iconshangxian" color="#3954FF"></BdpIcon>
</Button>
);
case 2:
default:
// 流程中和其他的状态展示上线的图标,但是要置灰!
return (
<Button type="link" disabled>
<BdpIcon type="iconshangxian" color="#DDD"></BdpIcon>
</Button>
)
}
}
// [])
测试
import React,{useMemo,useCallback,useState} from 'react';
const Test=()=>{
const [state,setState]=useState(10);
function handle(){
alert(state)
}
let getNum=useCallback(()=>{
return (
<>
{/* 由于没有依赖,而每次渲染都有自己的props和state,所以这个state是一直不会变的,
handle执行的时候按照作用域,应该是打印全局作用域的state,
但是这个时候的整个作用域的state就是初始的那个state */}
<h1>{state}</h1>
<button onClick={()=>{handle()}}>试试</button>
</>
)
},[])
return(
<>
<h1>{state}</h1>
<button onClick={()=>{setState(state+1)}}>添加</button>
{getNum()}
</>
)
}
export default Test;