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

Created on 1 Sep 2020  ·  6Comments  ·  Source: NervJS/taro


相关平台

微信小程序

小程序基础库: 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 

F-react T-weapp V-3

Most helpful comment

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

https://github.com/NervJS/taro/blob/9e03ecda6bc0a13dd8676d9c6c9b3333712056d1/packages/taro-runtime/src/next-tick.ts#L32

https://github.com/NervJS/taro/blob/9e03ecda6bc0a13dd8676d9c6c9b3333712056d1/packages/taro-runtime/src/dom/root.ts#L88-L96

All 6 comments

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

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

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

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

使用 useReady

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

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

https://github.com/NervJS/taro/blob/9e03ecda6bc0a13dd8676d9c6c9b3333712056d1/packages/taro-runtime/src/next-tick.ts#L32

https://github.com/NervJS/taro/blob/9e03ecda6bc0a13dd8676d9c6c9b3333712056d1/packages/taro-runtime/src/dom/root.ts#L88-L96

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

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

Was this page helpful?
0 / 5 - 0 ratings