Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dva subscriptions不生效 #2501

Open
hackerain opened this issue Oct 24, 2022 · 5 comments
Open

dva subscriptions不生效 #2501

hackerain opened this issue Oct 24, 2022 · 5 comments

Comments

@hackerain
Copy link

What happens?

所有介绍dva subscription使用方法的文档,包括官网,都是类似下面这种例子:

app.model({
  subscriptions: {
    setup({ dispatch, history }) {
      console.log('xxxx1');
      history.listen(({ pathname }) => {
        console.log('xxxx2');
        if (pathname === '/users') {
          console.log('xxxx3');
          dispatch({
            type: 'users/fetch',
          });
        }
      });
    },
  },
});

但是在umi 4.x版本下,却怎么也不生效,加上上面的console.log发现,只能打出来xxxx1,但是xxxx2和3始终没有触发。

相关环境信息

  • Umi 版本:4.0.24
  • Node 版本
  • 操作系统
@hackerain
Copy link
Author

hackerain commented Oct 24, 2022

经查排查发现 history 功能是使用的 https://github.com/remix-run/history 这个项目,它是react router依赖的项目,当前已经发布到了5.3.0,history.listen() api已经发生了变化,参见 history,现在history.listen()是这么写的:

// Listen for changes to the current location.
let unlisten = history.listen(({ location, action }) => {
  console.log(action, location.pathname, location.state);
});

在location中是包含pathname变量的:

  • location.pathname - The path of the URL、

而在4.x版本的history中,history.listen()是这么写的:

// Listen for changes to the current location.
const unlisten = history.listen((location, action) => {
  // location is an object like window.location
  console.log(action, location.pathname, location.state);
});

可见函数的参数从 (location, action) 变成了 {location, action},后者是一个析构参数,其实是从一个对象参数中析构出来的两个变量,而前者则是两个参数。可以从最新的5.3.0的history代码中,看到listen()定义中,现在只接受一个参数 update,而update包含2个变量:

listen(listener: Listener): () => void;

export interface Listener {
  (update: Update): void;
}

export interface Update {
  action: Action;
  location: Location;
}

所以当年写dva文档时,也就是umi 3.x的时候,应该还依赖的是4.x的history,但是到umi 4.x,由于其依赖的history到了5.x,listen() api发生了变化,导致listen()的函数没法被触发,所以umi 4.x对应的dva里的subscriptions得这么写才对:

app.model({
  subscriptions: {
    setup({ dispatch, history }) {
      console.log('xxxx1');
      history.listen(({ location, action }) => {
        console.log('xxxx2');
        if (location.pathname === '/users') {
          console.log('xxxx3');
          dispatch({
            type: 'users/fetch',
          });
        }
      });
    },
  },
});

@waittingbar
Copy link

路由切换是可以的,不过刷新后还是没有进到 history.listen 里面

@hackerain
Copy link
Author

同一问题:umijs/umi#9426

@hackerain
Copy link
Author

hackerain commented Oct 25, 2022

路由切换是可以的,不过刷新后还是没有进到 history.listen 里面

这个问题应该是因为旧版本的plugin-dva里面建dva时用的history是patch过的,在patch过的history中主动去调用了一次callback,所以刷新浏览器会主动执行一次dispatch,但是新版本的plugin-dva就是用的原生的history,就没这功能了。

dva/packages/dva/src/index.js

image

在3.x umi中的plugin-dva中,建dva app是这么建的:

  app = dva({
    history,
    
    ...(runtimeDva.config || {}),
    // @ts-ignore
    ...(typeof window !== 'undefined' && window.g_useSSR ? { initialState: window.g_initialProps } : {}),
    ...(options || {}),
  });

在这个逻辑里就会去走上面截图中建app的逻辑,将history给patch下。

在4.x umi中的plugin-dva中,建dva app是这么建的:

    app.current = create(
      {
        history,
        ...(runtimeDva.config || {}),
      },
      {
        initialReducer: {},
        setupMiddlewares(middlewares: Function[]) {
          return [...middlewares];
        },
        setupApp(app: IDvaApp) {
          app._history = history;
        },
      },
    );

这里面用的history就是原生的了,没有经过修改的。

patch过的history还修了一个挺严重的bug好像,现在不用这个了,不知道还会不会有问题:umijs/umi#2693

@wangwufan
Copy link

同样,我在umi3升级umi4后也发现这个问题,dva subscription切换路由能被侦听到,刷新就不行

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants