不要在useEffect(...),useMemo(...)或其他内置的Hook中调用Hook(动态导入)

时间:2020-07-09 07:52:18

标签: reactjs

const usePage = ({ page }) => {
  const prevPage = usePrevious(page)

  const [p, setPage] = useState()

  const loadData = async param => {
    const data = await import(`${param}`)
    setPage(data.default)
  }

  useEffect(() => {
    if (prevPage === page) return

    loadData(page)
  }, [page, prevPage])

  return {
    p
  }
}

const PageRoute = memo(({page}) => {
    const { p } = usePage({ page })

    const Page = p

    return (
      <Page/>
    )
  }
)

我不太了解这个问题与我的代码之间的关系。我没有在useEffect内调用任何钩子。我该如何解决?如果页面参数不等于前一个参数,我想在使用中调用动态导入。

1 个答案:

答案 0 :(得分:3)

问题在于,由于您可能是从这些动态导入的模块中默认导出一个React组件,因此data.default是一个传递给useState返回的setter的函数。

但是,由于useState设置程序也可以接受function which does the state update,所以我敢打赌,该设置程序调用了传递的函数,该函数是一个React组件(data.default),该函数会触发该组件中使用的钩子。因此,您的通话实际上等效于setPage(prev => data.default(prev))

可以通过显式传递您自己的状态更新程序(仅返回data.default函数)来解决此问题:

const loadData = async param => {
  const data = await import(`${param}`)
  setPage(() => data.default) // <-------
}