alibaba / rax

🐰 Rax is a progressive framework for building universal application. https://rax.js.org
Other
8k stars 627 forks source link

[BUG] 页面切换时,页面状态在 web 和小程序侧行为不一致 #2306

Closed fengzilong closed 2 years ago

fengzilong commented 2 years ago

Describe the bug

Demo

使用 npm init rax rax-example 分别创建 web 单页应用和 小程序跨端应用,新增一个页面,代码如下

import { createElement, useRef, useState } from 'rax';
import View from 'rax-view';
import { usePageShow } from 'rax-app';

export default function Home() {
  const ref = useRef(0);

  usePageShow(() => {
    ref.current += 1;
    console.log('pageshow ref', ref.current);
  });

  return (
    <View className={styles.homeContainer}></View>
  );
}

复现步骤:重复进入该页面多次,查看 Console 日志

小程序侧表现(截图为微信小程序,模拟器和真机调试结果一致)

Web 侧表现(chrome 浏览器)

根据日志中的结果可以推断出,在小程序上页面的组件实例并没有被销毁,而在 web 单页应用上,切换页面,会导致上一个页面被销毁

小程序上的这种行为,导致我们的开发同学使用了老的页面状态,并且试图在 usePageShow 中引用老的 state,但是这里又有一个坑,usePageShow 不支持传入第二个参数,导致读取的 state 永远是初始值

Expected behavior

usePageShow 在设计上并没有支持第二个参数,所以是不是应该保证小程序行为和 web 一致

但从另一个角度说,小程序没有销毁实例,会让切换页面的体验更好,尤其是页面本身是一个 webview 的情况下,不会触发 h5 页面重新加载,如果以小程序上的行为为准,需要为 usePageShow 补上第二个参数 deps,让 usePageShow 内的代码可以追踪状态变化

Additional context

SoloJiang commented 2 years ago
  1. 这个行为不一致性本质是容器导致的,从渲染角度来说小程序对应到端上应该是多 WebView 的 MPA 应用,如果是这样对标的话,在端上 Web 的表现和小程序就是一致的
  2. 从应用角度来说,本质是小程序在页面切换的时候能够保活上一个页面,所以在 rax-app v3.8.0 开始支持 SPA 页面配置保活
  3. 无论哪一种方式,由于容器和实际应用表现的差异性,很难做到真正的一致性