Tencent / wujie

极致的微前端框架
https://wujie-micro.github.io/doc/
Other
4.05k stars 580 forks source link

如何解决react子应用在react-devtools里失效 #612

Open wopelo opened 1 year ago

wopelo commented 1 year ago

描述bug 主应用和子应用均是react,在主应用中打开控制台,react-devtools无法检查子应用中的元素

如何复现 直接使用官方react主应用demo即可 尝试过将子应用的REACT_DEVTOOLS_GLOBAL_HOOK赋值为主应用的REACT_DEVTOOLS_GLOBAL_HOOK,看起来并没有效果

wopelo commented 1 year ago

找到一种无需修改子应用解决方案,完整代码参考 wujie-demo,主应用和子应用均为 react + vite,在主应用中:

import WujieReact from 'wujie-react'
import { useRef, useEffect } from 'react'

import './App.css'

function App() {
  // App在本地开发时会被执行多次
  const times = useRef(0)
  const isInita = useRef(0)
  const isInitb = useRef(0)

  useEffect(() => {
    times.current += 1
  }, [])

  return (
    <div className="App">
       <WujieReact
        width="100%"
        height="100%"
        name="project1"
        url="//localhost:8081/"
        plugins={
          [{ 
            jsBeforeLoaders: [{ 
              content: 'window.React = window.parent.React' 
            }, {
              content: 'window.ReactDOM = window.parent.ReactDOM' 
            }, {
              callback(appWindow) {
                isInita.current += 1

                if (isInita.current === times.current) {
                  appWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.__REACT_DEVTOOLS_GLOBAL_HOOK__
                }
              }
            }]
          }]
        }
      ></WujieReact>
      <WujieReact
        width="100%"
        height="100%"
        name="project2"
        url="//localhost:8082/"
        plugins={
          [
            {
              jsBeforeLoaders: [{
                callback(appWindow) {
                  isInitb.current += 1

                  if (isInitb.current === times.current) {
                    appWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.__REACT_DEVTOOLS_GLOBAL_HOOK__
                  }
                }
              }]
            }
          ]
        }
      ></WujieReact>
    </div>
  )
}

export default App

react-devtools 中的效果如图: image 用了点不优雅的方式,解决遇到的两个问题:

  1. 本地开发时,主应用 App 被执行了两次,一个表现就是 useEffect(() => { // ... }, []) 这种语句被执行了两次,如果不处理的话,appWindow.__REACT_DEVTOOLS_GLOBALHOOK__ = window.\_REACT_DEVTOOLS_GLOBALHOOK__ 被重复执行,导致 react-devtools 中同一个子应用出现多次。解决方法就是只在最后一次执行时挂载 \_REACT_DEVTOOLS_GLOBALHOOK_\
  2. 习惯上,将 react 应用命名为 APP,这会导致 react-devtools 中出现多个 App 标签,解决方案是子应用不命名为 APP。
wopelo commented 1 year ago

我看 vue 中也有类似的问题,比如 498,官方可否将这种用户比较hack的做法集成到无界的实现中去,搞个插件也行,在主应用中使用devtools调试子应用还是比较常见的需求。