Svelte reset 报错
Svelte 页面报错后导航反复出现 bind_this 读取 r 的异常,核对已销毁 boundary 的 reset 与 5.57.2 生命周期守卫。
页面渲染失败后切换路由,后面的每次导航却继续报:
Cannot read properties of null (reading 'r')
堆栈落在 bind_this,不一定是应用忘了检查绑定变量。若错误处理保存了 <svelte:boundary> 的 reset,而那个 boundary 已随条件分支销毁,应检查是否在重新调用过期的 reset。
这个具体场景在 Svelte 5.57.1、5.56.7 与 SvelteKit 3.0.0-next 的异步页面中出现过;Kit 的 next 版本不能当作稳定版范围。已核对的正式 Svelte 5.57.2 为销毁中的 boundary 加入生命周期守卫。
reset 属于产生它的 boundary
onerror 与 failed snippet 得到的 reset 用于清除当前边界的错误、重建其内容。它不是可供所有后续页面通用的刷新函数。
旧实现允许应用保存这个回调。原边界销毁后,effect 的组件上下文已清空,再调用旧 reset 却会重新进入渲染路径。子元素中的 bind:this 随后访问空上下文,才出现读取 r 的异常。仍存活的上层 boundary 还可能捕获这次新错误,保存另一份 reset,使问题在下一次导航重复。
排查时把错误发生、边界销毁、回调保存和再次调用的顺序连起来看。尤其检查布局是否按错误状态,在两个位置分别渲染同一份页面 children:状态切换会销毁原分支,旧回调却可能继续留在外部集合中。
这里只针对已经销毁的边界续行。一个仍存活的 boundary 内正常产生的 bind:this 错误,应继续检查自己的绑定与渲染条件,不能一概按过期 reset 处理。
让失效回调退出,保留正常恢复
5.57.2 在 reset 开始执行、以及延迟调用 onerror 前检查 boundary 是否已销毁或正在销毁。失效回调不再重启旧 effect;正常存活边界仍能清除错误并重新渲染。
选择与项目兼容、包含此修复的正式 Svelte 版本,并核对锁文件中实际解析到的依赖。只升级 Kit 的预发布包、或给 bind:this 增加一个泛用空值判断,都不能证明旧边界不会再次运行。
应用自己管理恢复回调时,也要让登记与清理跟随边界生命周期,避免把前一页的 reset 用在新页面。若布局确实可以保持同一个页面渲染位置,可用错误状态改变样式或周围内容,减少不必要的分支替换;前提是页面正常态与错误态的结构、权限和清理需求仍然满足业务设计。
不要在 onerror 的同步执行期间直接调用 reset。也不要把它做成无条件重试循环:活着的边界每次错误所提供的 reset 只能有效使用一次,重渲染仍可能遇到真实业务错误。
检查离开错误页之后
在获准的测试环境中,让页面产生一次可控的渲染错误,再离开错误页、继续导航。销毁后的 reset 和尚在队列中的错误处理不应重新渲染旧内容;存活边界的恢复操作仍应正常工作,原有卸载清理也不能跳过。
boundary 捕获的是渲染与 effect 期间的错误,不会自动接管普通事件处理器或与渲染无关的异步拒绝。若导航后报的是网络请求自身失败,应按请求生命周期处理,不能只靠 boundary 升级消除它。


