凌晨一点四十,测试环境那个订单页白屏了。
不是一直白,是在点筛选的时候白。本地跑一点事没有,我 npm run dev 开着,点了一百遍,筛选项从"待付款"点到"已取消",屁事没有。一上测试环境,点第二下,页面就没了,控制台红了一片。
最上面那行我到现在都记得:Maximum update depth exceeded.
我直译过来:最大更新深度超出。depth,深度嘛。我第一反应是组件嵌套太深了,我那个筛选栏外面套了个 Card,Card 外面套了个 Layout,Layout 外面还有一层,是不是层数太多了。想了十分钟,觉得不对,嵌套深也不该点一下就白屏啊。
查了下。又让 AI 用中文讲了一遍。大概是这个意思:这个 depth 不是"层数"的深度,是"次数"——setState 被反复调用,调到一定次数 React 就不干了,直接把你的组件关掉。跟嵌套一点关系没有,我想的那个深度是 DOM 树的深度,两码事。同一个词,两个意思,我又是先撞上错的那个。
问题出在我那段 useEffect 里。我在里面 setFilteredList,依赖数组里放了 filter 这个对象。filter 是我在父组件里直接写的 { status: 'all', page: 1 },每次渲染都是一个新对象。所以:渲染 → filter 是新的 → effect 跑 → setState → 再渲染 → filter 又是新的 → effect 又跑。死循环。React 数到第五十次就把我掐了。
这里有个词我又卡了一下,reference。我查词典,上面写的是"参考、提及、引用文献",跟这个场景八竿子打不着。AI 说这里的意思是"引用",内存里的地址。每次写一个对象字面量,地址就是新的,虽然内容长的一模一样。我大概是懂了,但你要我现在解释清楚我解释不了。反正就是我写了个长得一样的对象,React 认为它是俩。
中间我还踩了个更蠢的。我第一反应是把依赖数组删掉,[] 一放,果然不报了,页面也不白了。我高兴了大概三分钟,然后发现筛选点了没用,列表根本不动。因为 effect 只在挂载的时候跑一次,后面点了它不管。等于我把报警器电池拔了,说火灭了。
后来改了两处,一处是用 useMemo 把 filter 包起来,另一处是把依赖拆成 status 和 page 两个基本类型。改完刷新,点了七八下,正常。时间三点出头。
我给同事发消息,没人回,正常,这个点鬼都不回。煮了个泡面,坐在椅子上吃完,又盯着屏幕看了会儿,怕它趁我睡着再白。没白。
今日单词:reference,引用,我记得我查过这个词,第三次了还是记不住,下次还得查。