首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加载反应钩使用动态导入?

加载反应钩使用动态导入?
EN

Stack Overflow用户
提问于 2020-07-28 02:55:18
回答 2查看 3.4K关注 0票数 10

我正在使用一些第三方反应钩子库,这些库并不是初始呈现所必需的。例如react-use-gesturereact-springreact-hook-form。它们都提供了交互性,这可以等到UI呈现之后。在呈现组件之后,我希望使用Webpack的代码分解(即import())动态加载这些组件。

但是,我不能将一个React钩子存根掉,因为它本质上是一个条件钩子,它不支持React。

我能想到的两个解决方案是:

  1. 以某种方式将钩子提取到组件中并使用组合。
  2. 在钩子负载后,力对重建构件的反应

这两种解决方案似乎都很麻烦,很可能未来的工程师会把它搞砸。有更好的解决办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-16 14:59:04

正如您所说的,使用延迟加载的钩子有两种方法:

  1. 在父组件中加载库,在可用时使用库有条件地呈现组件

与…有关的东西

代码语言:javascript
复制
let lib
const loadLib = () => {...}

const Component = () => {
  const {...hooks} = lib
  ...
}

const Parent = () => {
  const [loaded, setLoaded] = useState(false)
  useEffect(() => loadComponent().then(() => setLoaded(true)), [])
  return loaded && <Component/>
}

这个方法确实有点麻烦,每个库都要做大量的手工工作。

  1. 使用钩子开始加载组件,失败,在加载钩子时重新构建组件

这可以在React.Suspense的帮助下被简化

代码语言:javascript
复制
<Suspense fallback={"Loading..."}>
  <ComponentWithLazyHook/>
</Suspense>

悬念工作类似于错误边界,如下所示:

  1. 组件在呈现过程中抛出承诺(通过React.lazy或手动)
  2. 悬念抓住了这一承诺,并造成了退步。
  3. 承诺决意
  4. 悬念重呈现组件

数据获取的悬念从实验阶段成熟时,这种方式可能会变得更加流行。

但是,为了只加载一次库,并可能缓存结果,一个简单的数据获取实现可以做到这一点。

代码语言:javascript
复制
const cache = {}
const errorsCache = {}
// <Suspense> catches the thrown promise
// and rerenders children when promise resolves
export const useSuspense = (importPromise, cacheKey) => {
  const cachedModule = cache[cacheKey]
  // already loaded previously
  if (cachedModule) return cachedModule

  //prevents import() loop on failed imports
  if (errorsCache[cacheKey]) throw errorsCache[cacheKey]

  // gets caught by Suspense
  throw importPromise
    .then((mod) => (cache[cacheKey] = mod))
    .catch((err) => {
      errorsCache[cacheKey] = err
    })
};

const SuspendedComp = () => {
  const { useForm } = useSuspense(import("react-hook-form"), "react-hook-form")
  const { register, handleSubmit, watch, errors } = useForm()
  ...
}

...

<Suspense fallback={null}>
  <SuspendedComp/>
</Suspense>

您可以看到一个示例实现这里

编辑:

当我用codesandbox编写这个例子时,我完全没有意识到,依赖解决方案的行为将不同于webpack在本地的行为。

Webpack import() 不能完全处理动态路径喜欢import(importPath)。它必须有静态的import('react-hook-form'),以便在构建时创建一个块。

因此,我们必须自己编写import('react-hook-form'),并提供用作缓存键的importPath = 'react-hook-form'

我将代码框示例更新为与webpack一起工作的示例,旧示例不能在本地工作,可以找到这里

票数 10
EN

Stack Overflow用户

发布于 2020-08-16 15:41:34

你考虑过把钩子钉死了吗?我们使用了类似于异步加载一个大库的东西,但它不是一个钩子,所以YMMV。

代码语言:javascript
复制
// init with stub
let _useDrag = () => undefined;

// load the actual implementation asynchronously
import('react-use-gesture').then(({useDrag}) => _useDrag = useDrag);

export asyncUseDrag = (cb) => _useDrag(cb)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63126355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档