Umi: 在全局model的history.listen中调用dispatch,同时Link的to属性添加query参数会导致栈溢出

Created on 25 Jun 2019  ·  7Comments  ·  Source: umijs/umi

What happens?

  1. 全局model调用dispatch
//src/models/test.js 

export default {
  namespace: 'test',
  reducers: {
    updateState(state, { payload }) {
      return {
        ...state,
        ...payload,
      };
    },
  },
  subscriptions: {
    setup({ dispatch, history }) {
      return history.listen(location => {
        //这里写会栈溢出
        dispatch({
          type: 'updateState',
          payload: {
            a: 1,
          },
        });
      });
    },
  },
};
  1. Link的to属性添加query参数
// src/pages/list/index.js
import Link from 'umi/link';

export default () => {
  // to加上query会导致栈溢出
  return <Link to={{ pathname: '/user', query: { a: 1 } }}>跳转到user</Link>;
};

两个步骤同时满足就会栈溢出。
在src/pages/list/model.js中dispatch不会栈溢出
Link的to属性不加query不会栈溢出

Mini Showcase Repository(REQUIRED)

Provide a mini GitHub repository which can reproduce the issue.
Use yarn create umi then upload to your GitHub


https://github.com/feibi/umi-bug.git

Expected behavior

  1. 期望全局model与局部model表现一致,不会栈溢出

Context

  • Umi Version: 2.8.3
  • Umi-plugin-react Version: 1.8.4
  • Node Version: v10.15.0
  • Platform: window 10
PR Welcome type(bug)

Most helpful comment

新版本有这个问题,在 subscriptions 里面调用请求,会无限请求,最终栈溢出

subscriptions: {
    setup({ dispatch, history }) {
      return history.listen(location => {
        //这里写会栈溢出
        dispatch({
          type: 'updateState',
        });
      });
    },
  },

在以下版本没有这个问题

[email protected] 
[email protected]

@sorrycc

临时方案:项目中安装 [email protected] ,此方案不适用于二次封装 umi 的库,如 alitajs 等,最终安装的还是测试版

All 7 comments

我也碰到过这个这个问题。。开发环境遇到过,正式环境没有遇到

我也是这个,有好的解决方法嘛

需要花时间看,可能和 react-reudx 升级有关。

这个问题有点严重鸭~~ 组件里面想跳转一下路由。 只要在订阅里面有diapatch就会栈溢出

找到了一种曲线救国的解决办法。
问题产生主要是在 subscriptions的history.listen中调用dispatch,其实需求就是想在路由变化时去处理一些逻辑。
所以可以不使用history.listen而在其他地方监听路由变化,绕开这个bug。
具体写法如下:
第一步在全局layouts/index.js中监听路由变化,因为路由变化时会重新触发这里的render。

// src/layouts/index.js

let oldLocation = {};
const listenRoute = (props)=>{
  const { location, dispatch } = props;
  //路由地址发生变化时,触发 onRouteChange action
  if(location.pathname !== oldLocation.pathname){
    dispatch({
      type:'onRouteChange',
      location
    });
  }
  oldLocation = location;
};

function BasicLayout(props) {
  listenRoute(props)
  return (
    <div>
      {props.children}
    </div>
  );
}

export default BasicLayout;

第二步对应model (这里是 全局global)监听等待匹配 onRouteChange action

// src/models/global.js

export default {
  namespace: 'global',

  state: {
    location: null
  },

  subscriptions:{
    setup({ dispatch }){
      dispatch({ type: 'test'})
    }
  },
  effects: {
    * test(_, { take, put }) {
      while (true) {
        const { location } = yield take('onRouteChange');
        /*
        * 每次路由变化,这里的逻辑都会执行一遍。可以吧原本要写在history.listen中的逻辑放在这里。
        * 这里的location是目标路由的路由信息。
        * */
        yield put({
          type: 'changeState',
          payload :{
            location
          }
        })

      }
    },
  },

  reducers: {
    changeState(state, { payload }) {
      return {
        ...state,
        ...payload,
      };
    },
  },
};

新版本有这个问题,在 subscriptions 里面调用请求,会无限请求,最终栈溢出

subscriptions: {
    setup({ dispatch, history }) {
      return history.listen(location => {
        //这里写会栈溢出
        dispatch({
          type: 'updateState',
        });
      });
    },
  },

在以下版本没有这个问题

[email protected] 
[email protected]

@sorrycc

临时方案:项目中安装 [email protected] ,此方案不适用于二次封装 umi 的库,如 alitajs 等,最终安装的还是测试版

一样的问题

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Artoria-0x04 picture Artoria-0x04  ·  3Comments

ddzy picture ddzy  ·  3Comments

miaojinxing picture miaojinxing  ·  3Comments

ironyfive picture ironyfive  ·  3Comments

sorrycc picture sorrycc  ·  4Comments