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

lazy导致的两次渲染 #28

Closed
henryzp opened this issue Jun 30, 2020 · 7 comments
Closed

lazy导致的两次渲染 #28

henryzp opened this issue Jun 30, 2020 · 7 comments

Comments

@henryzp
Copy link

henryzp commented Jun 30, 2020

这里有一个bug,github地址是:https://github.com/henryzp/concent-test-demo

image

我的疑问是tab切换时,为什么tabContainer组件会render两次。。

export async function changeTabComplex(
  key: string,
  moduleState: TihaiState,
  actionCtx: IAC,
) {
  await actionCtx.dispatch(changeActiveTabKey, key);
  await actionCtx.dispatch(getTableList, { key, current: 1, pageSize: 10 });
  await actionCtx.dispatch(getTableList, { key, current: 2, pageSize: 10 });
}

export async function changeTab(
  key: string,
  moduleState: TihaiState,
  actionCtx: IAC,
) {
  await actionCtx.lazyDispatch(changeTabComplex, key);
}

触发的是changTab

期望的结果是render一次。。。

@fantasticsoul
Copy link
Contributor

fantasticsoul commented Jun 30, 2020

你在run函数加一个log 函数看看 渲染触发原因,然后再报告给我看下log 记录

run( {}, {
  middlewares:[(stateInfo, next)=>{
    console.warn(stateInfo);
    next();
  }],
});

@fantasticsoul
Copy link
Contributor

fantasticsoul commented Jun 30, 2020

对了,最新的react提供了 React.StrictMode 组件来包装根组件,然后触发双调用来故意触发两次渲染,以便排除一些渲染过程中书写了副作用代码导致的bug,该特性仅在开发模式有效,生产模式会关闭,更多信息可参考:

http://react.html.cn/docs/strict-mode.html
https://frontarm.com/daishi-kato/use-ref-in-concurrent-mode/

你可以写个普通组件测试一下,就明白原因了

btw,提几个优化点😀

1 源头处也支持触发lazy,这样就可以不用再reducer里写lazy了
https://github.com/henryzp/concent-test-demo/blob/master/src/pages/tihai/index.tsx

changeTab: (key: string) => ctx.mr.changeTab(key),
// 可改为
changeTab: (key: string) => ctx.mr.changeTab(key, {lazy:true}),

2 可以写个setState,替代无逻辑的reducer函数

export function changeActiveTabKey(key: string) {
  return {
    activeTabKey: key,
  };
}

export function setModalVisible(visible: boolean) {
  return {
    modalVisible: visible,
  };
}

// 可改为
export function setState(partialState){
  return partialState;
}

@henryzp
Copy link
Author

henryzp commented Jun 30, 2020

image

@henryzp
Copy link
Author

henryzp commented Jun 30, 2020

@fantasticsoul ,hi,你的建议很棒,非常感谢。。

不过上面说的问题,还是没有排查出来原因。。。你方便代码clone下来,跑一下么?我是把公司的那个项目给最小化精简了,然后用了umi3的脚手架,启动是没有问题的

@fantasticsoul
Copy link
Contributor

我测了下,umi没有使用StrictMode,你提到的问题原因已找到
concent本身是精确通知到位了的,这里的两次渲染时react组件自上而下株连式的渲染导致的,你只需要包装React.memo即可

export default React.memo(() => {
  console.log('2222222222');
  // your code
});

@henryzp
Copy link
Author

henryzp commented Jun 30, 2020

@fantasticsoul ,没有明白react组件自上而下株连式的渲染。。能详细说一下么?或者给个资料也行。。。

@fantasticsoul
Copy link
Contributor

@fantasticsoul ,没有明白react组件自上而下株连式的渲染。。能详细说一下么?或者给个资料也行。。。

React的渲染时自顶向下的

<A><B><C/></B></A>

如果A触发渲染了,没有优化机制的话默认会把他所有的孩子跟着一起渲染,所以才让你包一个memo

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

2 participants