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

刚升级了3.0.8,发现useEffect和useLayoutEffect的执行时机和预期的不一致,无法在其中获取元素宽高 #7491

Closed
allendongyx opened this issue Sep 1, 2020 · 10 comments
Labels
F-react Framework - React N-doc_needed 需要被在文档中进行记录 T-weapp Target - 编译到微信小程序 V-3 Version - 3.x

Comments

@allendongyx
Copy link

相关平台

微信小程序

小程序基础库: 2.11.3
使用框架: React

复现步骤

  useLayoutEffect(() => {
    Taro.createSelectorQuery()
      .select('#user-header')
      .fields(
        {
          size: true
        },
        res => {
          if (res) {
            console.log('res: ', res)
            setHeaderHeight(res.height)
          }
        }
      )
      .exec()
  }, [isLogin, userInfo])

补充,在useEffect中也不行

期望结果

res 返回空

实际结果

获取渲染后的组件宽高

环境信息

👽 Taro v3.0.8


  Taro CLI 3.0.8 environment info:
    System:
      OS: macOS 10.14.6
      Shell: 3.2.57 - /bin/bash
    Binaries:
      Node: 10.21.0 - ~/.nvm/versions/node/v10.21.0/bin/node
      Yarn: 1.22.4 - ~/.nvm/versions/node/v10.21.0/bin/yarn
      npm: 6.14.4 - ~/.nvm/versions/node/v10.21.0/bin/npm
    npmPackages:
      @tarojs/components: 3.0.8 => 3.0.8 
      @tarojs/mini-runner: 3.0.8 => 3.0.8 
      @tarojs/react: 3.0.8 => 3.0.8 
      @tarojs/runtime: 3.0.8 => 3.0.8 
      @tarojs/taro: 3.0.8 => 3.0.8 
      @tarojs/webpack-runner: 3.0.8 => 3.0.8 
      babel-preset-taro: 3.0.8 => 3.0.8 
      eslint-config-taro: 3.0.8 => 3.0.8 
      react: ^16.13.1 => 16.13.1 
      taro-ui: ^3.0.0-alpha.3 => 3.0.0-alpha.3 
@taro-bot2 taro-bot2 bot added F-react Framework - React T-weapp Target - 编译到微信小程序 V-3 Version - 3.x labels Sep 1, 2020
@allendongyx
Copy link
Author

尝试使用jquery like 的方式也不行

$('user-header').height()

看到
https://github.com/liuhuapiaoyuan/taro-linui/blob/2c69e691e6d12ff82ec6db402051f8066b9eae72/taro-linui/src/components/LAlbum.tsx

这个哥们在useLayoutEffect中使用递归的方式来获取宽高,如果获取失败就持续递归,直到获取成功

@Chen-jj
Copy link
Contributor

Chen-jj commented Sep 1, 2020

使用 useReady

@allendongyx
Copy link
Author

@Chen-jj useReady 只会执行一次啊,我的需求是需要根据用户是否登录,用户信息的标签长度,获取高度,这个view是一个flex布局的

@Chen-jj
Copy link
Contributor

Chen-jj commented Sep 1, 2020

useEffect、 useLayoutEffect 都是 React 根据 DOM API 执行情况来触发的,而 Taro 3 DOM 层是在小程序逻辑层模拟的,setData 完成后才能用 selectorQuery 获取小程序 DOM 的尺寸信息。你可以试试在 useEffect 里调用 Taro.nextTick,在 nextTick 继续获取小程序 DOM,这个 nextTick 应该能确保是 setData 回调里执行。

pageElement.enqueueUpdateCallbak(cb, ctx)

ctx.setData(data, () => {
perf.stop(SET_DATA)
if (!this.pendingFlush) {
this.flushUpdateCallback()
}
if (initRender) {
perf.stop(PAGE_INIT)
}
})

@allendongyx
Copy link
Author

通过nextTick和setTimeOut(100) 基本解决了这个问题,没有复现过~

@Chen-jj
Copy link
Contributor

Chen-jj commented Sep 2, 2020

👍🏻👍🏻👍🏻💪💪💪老哥有空的话欢迎吧问题与解决办法提个 PR 到文档,指引其他开发朋友~

@Chen-jj Chen-jj added the N-doc_needed 需要被在文档中进行记录 label Sep 19, 2021
@wozien
Copy link

wozien commented Mar 1, 2023

通过nextTick和setTimeOut(100) 基本解决了这个问题,没有复现过~

为啥要需要setTimeout?

@yoyo837
Copy link
Contributor

yoyo837 commented Mar 1, 2023

setTimeout 能解决一些时序问题, 但是不是可靠的.

@wozien
Copy link

wozien commented Mar 1, 2023

对呀!页面级的可以直接 useReady 加 nextTick

@wzhqwq
Copy link

wzhqwq commented Jun 11, 2023

这个解决方案并不适用于在setState后立即调用(被坑了一上午),主要原因是Taro.nextTick的逻辑在对 #10179 的修复中被改动了,enqueueUpdateCallback只有在pendingUpdatetrue时才会被调用,而众所周知setState不会立即触发DOM更新,所以如果在setState后立即调用Taro.nextTick,是不会把回调加入到setData回调中的(而是会给setTimeout(cb, 1))。
正确做法要么是在useEffect里用,要么是再嵌套setTimeout(fn, 0),如此一来就可以在触发DOM更新时,在pendingUpdate被改回false前调用Taro.nextTick了。
像这样:

// set some states
setTimeout(() => {
  Taro.nextTick(() => {
    // render ready
  })
}, 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
F-react Framework - React N-doc_needed 需要被在文档中进行记录 T-weapp Target - 编译到微信小程序 V-3 Version - 3.x
Projects
None yet
Development

No branches or pull requests

5 participants