gpt4 book ai didi

javascript - yarn 工作区和 lerna 导致无效的 Hook 调用

转载 作者:行者123 更新时间:2023-12-05 00:38:48 25 4
gpt4 key购买 nike

我认为这是 重复 React 问题
当前行为:
container项目,当我路由到 sub-app/foo 时它工作正常.但是当我路由到 sub-app我收到以下错误:

Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
通知: sub-app/foo将获得一个类组件。 sub-app将获得一个 React hooks 组件
预期行为 : 我期望的结果是 subApp代码将在 container 中正常工作
项目结构:
/mono-repo
packages
- container
- subApp
// /packages/container/src/App.js
import React from 'react'
import { BrowserRouter, Switch, Route, Link } from 'react-router-dom';
import About from './About';
import Header from './Header';
import Loadable from 'react-loadable'

const Logo = () => {
return <div>LOGO</div>
}

const loadableComponent = (loader) => {
return Loadable({
loader: () =>
loader().then(
(res) => {
return res
},
(e) => () => {
console.log(e)
}
),
loading() {
return (
<div>loading</div>
)
}
})
}

const loadSubApp = (subAppInfo) => {
const { name, host } = subAppInfo
return new Promise((resolve, reject)=> {
fetch(`${host}/${name}/asset-manifest.json`)
.then(res => res.json())
.then(manifest => {
const script = document.createElement('script');
script.src = `${host}${manifest.files['main.js']}`;
const timeout = setTimeout(()=>{
console.error(`MicroApp ${name} timeout`);
reject(new Error(`MicroApp ${name} timeout`));
},20000)
script.onload = () => {
clearTimeout(timeout)
const app = window[name]
console.log({app, name})
console.log(`MicroApp ${name} loaded success`);
resolve(app)
}
script.onerror = (e) => {
clearTimeout(timeout);
console.error(`MicroApp ${name} loaded error`, e);
reject(e)
}
document.body.appendChild(script);
})
})
}

const subLoader = (name) => async () => {
const App = await loadSubApp({ name: 'subApp', host: process.env.REACT_APP_SUBAPP_HOST })
console.log({App, window})
return App[name]
}



const App = () => {
return (
<BrowserRouter>
<React.Fragment>
<Logo />
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/header">header</Link>
</li>
<li>
<Link to="/sub-app">subApp</Link>
</li>
<li>
<Link to="/sub-app/foo">subApp foo</Link>
</li>

</ul>
<Switch>
<Route exact path="/" component={About} />
<Route exact path="/header" render={() => <Header /> }/>
<Route exact path="/sub-app/foo" render={()=> {
const RenderSubApp = loadableComponent(subLoader('Foo'))
return <RenderSubApp />
}}/>
<Route exact path="/sub-app" render={()=> {
const RenderSubApp = loadableComponent(subLoader('Count'))
return <RenderSubApp />
}}/>
</Switch>
</React.Fragment>
</BrowserRouter>
)
}

// /packages/subApp/config-overrides.js
const {
override,
// addWebpackAlias
} = require("customize-cra");
// const path = require("path");

const dropConsole = () => {
return (config) => {

if (config.optimization.minimizer) {
config.optimization.minimizer.forEach((minimizer) => {
if (minimizer.constructor.name === "TerserPlugin") {
minimizer.options.terserOptions.compress.drop_console = true;
}
});
}
return config;
};
};

const optBuild= () => config => {
config.optimization.runtimeChunk = false;
config.optimization.splitChunks = {
cacheGroups: {
default: false,
},
};
return config
}

const disableSourceMap = () => (config) => {
if (process.env.NODE_ENV === "production") {
config.devtool = false;
}
return config;
};

const customizeCraOverride = override(
disableSourceMap(),
dropConsole(),
optBuild(),
// addWebpackAlias({
// 'react': path.resolve(__dirname, '../container/node_modules/react'),
// 'react-dom': path.resolve(__dirname, '../container/node_modules/react-dom')
// })
);

const webpack = (config, env) => {
const webpackConfig = customizeCraOverride(config, env);

return {
...webpackConfig,
output: {
...webpackConfig.output,
library: "subApp",
libraryTarget: 'window',
},
// externals: {
// 'react': 'react',
// 'react-dom': 'react-dom'
// },
};
};

module.exports = {
webpack,
};
项目链接 bug-demo
这些解决方案对我不起作用
  • https://reactjs.org/warnings/invalid-hook-call-warning.html
  • https://github.com/facebook/react/issues/13991
  • https://github.com/facebook/react/issues/15315
  • Solve having more than one copy of React in the same app
  • Yarn Workspaces and Invalid Hook call
  • 最佳答案

    终于解决了这个问题。

    // /packages/subApp/config-overrides.js

    ...

    const webpack = (config, env) => {
    const webpackConfig = customizeCraOverride(config, env);

    return {
    ...webpackConfig,
    output: {
    ...webpackConfig.output,
    library: "subApp",
    libraryTarget: 'window',
    },
    externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
    },
    };
    };
    module.exports = {
    webpack
    };

    // packages/container/src/index.js

    ...

    export {
    React,
    ReactDOM
    }
    // packages/container/config-overrides.js

    ...

    const webpack = (config, env) => {
    const webpackConfig = customizeCraOverride(config, env);
    return {
    ...webpackConfig,
    output: {
    ...webpackConfig.output,
    libraryTarget: 'umd',
    },
    }
    };
    module.exports = {
    webpack
    };

    关于javascript - yarn 工作区和 lerna 导致无效的 Hook 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71464758/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com