react 可以拿到最新数据吗?

2022-07-25 17:17:13 +08:00
 heishu

切换页码时,保存新页码,重新请求新页码数据

const [pagination, setPagination] = useState({currentPage: 1, ...}) //多余属性没写,如 pageSize 等
const pageChanged = (newPage) => {

    // 这里用 useState 和 useReducer ,requestData 都无法拿到最新页码数据
    setPagination((prev) => ({...prev, currentPage: newPage}));
    
    requestData(); // 这里可以用定时器 100ms 后再执行,以便于拿到最新数据吗?
}

const requestData() => {
    // 最新页码不通过函数传参的方法传递,就拿不到最新数据。。。
    console.log(pagination.currentPage); //这里拿不到最新的页码
}
1730 次点击
所在节点    前端开发
20 条回复
max21
2022-07-25 17:19:10 +08:00
用 useRef 可以
mufeng
2022-07-25 17:20:54 +08:00
useCallback
heishu
2022-07-25 17:22:00 +08:00
@max21 useRef 不会触发页码渲染啊
lalalaqwer
2022-07-25 17:28:01 +08:00
在 useEffect 中请求。你要知道为什么拿不到新数据,因为你的函数创建的时候是用的旧数据。要用新数据你就得重新创建函数。
heishu
2022-07-25 17:36:21 +08:00
@lalalaqwer useCallback 和 useEffect 意义应该差不多在这里,不过我有个问题是,当有筛选项生效时,需要将 currentPage ,pageSize 等多个值重置为默认值,在 useEffect 中放入这些依赖项的话会触发多次请求的哇?
towave
2022-07-25 17:45:20 +08:00
传参最好,其次 useRef 可以的,两个都用不就行了
anjianshi
2022-07-25 18:10:08 +08:00
我专门给这种场景写了个工具 hook

function useStateWithRef(initialState) {
const [state, rawSetState] = useState(initialState)
const ref = useRef(state)
const setState = useCallback((value) => {
ref.current = value
rawSetState(value)
}, [])
return [state, setState, ref]
}

const [state, setState, stateRef] = useStateWithRef(1)
需要随时获取最新值的地方用 ref ,其他地方用 state
heishu
2022-07-25 18:35:35 +08:00
@anjianshi 你这个是绑定 dom 用 state ,函数中拿到最新数据用 stateRef 吗?
ryougifujino
2022-07-25 18:36:21 +08:00
setter 的更新是异步的,马上去取肯定拿不到。
fayetitus
2022-07-25 19:40:31 +08:00
但我不理解,你为什么要避免给 requestData 传参呢?
如果你的 pageChanged 是个 handler (起码从名字上看,我猜它视),在这里直接传参调用 requestData 是个非常符合 react 哲学的事情。
throns
2022-07-25 20:23:17 +08:00
推荐看一下 Dan 写的文章: https://beta.reactjs.org/learn/synchronizing-with-effectshttps://beta.reactjs.org/learn/you-might-not-need-an-effect
1 、这里的正常操作是:事件调用后,计算最新的筛选项(包括页码和其他的筛选项目),筛选项可以用 state 存起来,把筛选项作为参数传给请求函数进行调用。
2 、不要滥用 useEffect ,useEffect 会让你很容易会有响应式思想,页码变了,setState 更新页码,然后 useEffect(() =>{ 请求函数 }, [pagination]),这样子会让代码很难维护和问题跟踪。只要是事件触发的操作都尽量避免使用 useEffect 。
3 、数据请求的话,推荐用 SWR 或者 react-query ,你自己封装也可以,不建议在代码中直接用 useEffect 来写。用请求库能让你的工作事半功倍,这也是 Dan 推荐的( Keep in mind that modern frameworks provide more efficient built-in data fetching mechanisms than writing Effects directly in your components.)
useEffect 我个人觉得不是一个很好的 Api ,对使用者的心智负担很大,Dan 的两篇文章里面不推荐的用法我基本都写过。官方最近考虑新增一个 API: https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md
Leviathann
2022-07-25 21:01:35 +08:00
你这个就是典型的 pub sub 的思维啊,和 react 推崇的不符
yazoox
2022-07-25 23:12:43 +08:00
楼主,能不能不要用代码,而是先用文字详细描述一下你的需求么?反正我是不知道你要干嘛。
heishu
2022-07-26 09:18:20 +08:00
@fayetitus 通过传参传递数据是符合 react 思想的吗,如果是的话我就向这个方向改写了
heishu
2022-07-26 09:18:31 +08:00
@Leviathann 通过传参传递数据时副歌 react 思想的吗,如果是的话我就向这个方向改写了
fayetitus
2022-07-26 10:27:57 +08:00
@heishu 实打实是的,你解除 requestData 对 currentPage 的依赖,使其变成了一个纯函数。把这个 requestData 当做是 event handler 的一部分,而不是 effect 这个黑大粗概念,这是一种比较好的写法。在没啥时间的时候这么做也足够了。

更好的写法在 @throns 列出的文档中。尤其是 you may not need useEffct 里专门有一节 fetching data ,使用的样例正是分页请求,解释了现代 react 中怎么实践请求。

有时间的话,最好通读那些文档。悟道后记得找个现代请求库,比如 swr 之类的,别自己再造轮子……
zhangleshiye
2022-07-29 21:26:23 +08:00
@throns 看了下 重新回顾了下 感觉还是不一样啊
throns
2022-07-29 23:17:47 +08:00
@zhangleshiye 不知道你哪里感觉不一样。不过有不同的体会很正常,我的很多体会都是做需求思考得来的。就举个简单的例子:一个列表页,进到页面默认请求第一页的数据(得用 useEffect),可以切换页码请求新的数据。有筛选项,修改筛选项后,此时页码要重置到 1 再请求数据,如果页码和筛选项不是维护到一个 useState 的话,就会很麻烦。为了调用请求函数的时候拿到重置后的页码值,这时候你就本能地想到得用 useEffect 来处理,筛选项和页码变了再调用请求函数,这时候你会发现请求了两次。这个简单的例子,我觉得很多人会遇到过,看 Dan 写的两个文档,立马就应该知道要将筛选项传给请求函数,而不是用 useEffect 。随着业务复杂,你可能会发现 react hook 其实不怎么好用,这也是为什么有一些人很排斥。感觉你之前应该没怎么写过 hook ,你现在看那些文档,我觉得很难有体会,很正常,多踩坑多思考。
zhangleshiye
2022-07-30 01:15:00 +08:00
我就是说重读文档感受不一样了 22223
zhangleshiye
2022-07-30 01:17:36 +08:00
@throns 就是隔了几天重新看文档, 有新体会的意思

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/868603

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX