【问题标题】:Why is export from index.tsx file undefined? (React + Typescript)为什么从 index.tsx 文件导出未定义? (反应 + 打字稿)
【发布时间】:2022-02-19 11:51:37
【问题描述】:

我有一个简单的上下文提供程序,我想将其导出为 npm 包。

我使用 create-react-library 创建了我的 npm 包。

我创建了一个 index.tsx 文件,当从另一个项目导入这个 npm 包时可以访问该文件; 我将 Context Provider 导入到这个 index.tsx,然后将其导出。

当我尝试使用从 index.tsx 导入的 ContextProvider 运行测试时,导入的对象是 undefined(即使我可以在 VS Code 中导航到它)。但是,当我直接从源导入它时,它工作正常。我需要让它从 index.tsx 文件中运行,以便通过 npm 包访问它。

谁能向我解释一下我在这里缺少什么?

src/index.tsx

import ErrorHandler from './contexts/ErrorHandlerContextProvider'

export { ErrorHandler }

// export { default as ErrorHandler } from './contexts/ErrorHandlerContextProvider' //<-- no luck

src/index.test.tsx

// import ErrorHandler from './contexts/ErrorHandlerContextProvider' // <-- this import works
import { ErrorHandler } from '.'

describe('ErrorHandlerContextProvider', () => {
  it('is truthy', () => {
    expect(ErrorHandler.ErrorHandlerContextProvider).toBeTruthy()
  })
})

src/contexts/ErrorHandlerContextProvider.tsx

import React, { createContext, FC, useContext } from 'react'
import PropTypes from 'prop-types'

type errorHandlerContextType = {
  handleError: (error: Error, info: string) => Promise<void>
}

const ErrorHandlerContext = createContext<errorHandlerContextType | null>(null)

const useErrorHandlerContextProvider = () => {
  return useContext(ErrorHandlerContext)
}

const ErrorHandlerContextProvider: FC = ({ children }) => {

  const handleError = (error: Error, info: string): Promise<void> => {
    console.log('error', error)
    console.log('info', info)

    return Promise.reject(error)
  }

  return (
    <ErrorHandlerContext.Provider value={{ handleError }}>
      {children}
    </ErrorHandlerContext.Provider>
  )
}

ErrorHandlerContextProvider.propTypes = {
  children: PropTypes.node.isRequired
}

export default { ErrorHandlerContextProvider, useErrorHandlerContextProvider }

/tsconfig.json

{
  "compilerOptions": {
    "outDir": "dist",
    "module": "esnext",
    "lib": ["dom", "esnext"],
    "moduleResolution": "node",
    "jsx": "react",
    "sourceMap": true,
    "declaration": true,
    "esModuleInterop": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "allowSyntheticDefaultImports": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "example"]
}

npm 运行测试

失败 src/index.test.tsx ● ErrorHandlerContextProvider › 是真实的

TypeError: Cannot read property 'ErrorHandlerContextProvider' of undefined

  4 | describe('ErrorHandlerContextProvider', () => {
  5 |   it('is truthy', () => {
> 6 |     expect(ErrorHandler.ErrorHandlerContextProvider).toBeTruthy()
    |                         ^
  7 |   })
  8 | })
  9 |

  at Object.<anonymous> (src/index.test.tsx:6:25)

【问题讨论】:

  • 暂时忘记测试:TS 编译器是否成功构建了这个项目,还是因为找不到模块而崩溃?
  • tsc 运行良好,没有错误。
  • 请同时发布您的 tsconfig。我想我将不得不在本地实际运行它才能弄清楚。 (如果您可以共享一个 repo 会更好,但如果这不可接受,我认为只需配置 + 已发布的代码就足够了。)
  • 谢谢@Tom。回复较晚,抱歉。我已经添加了 tsconfig 以及我用来创建库的包的链接。我决定暂时使用 JS 而不是 TS,只是为了让事情顺利进行,但计划尽快让 TS 工作。再次感谢!

标签: javascript reactjs typescript npm


【解决方案1】:

这看起来很可疑:

// src/index.test.tsx

// works
// import ErrorHandler from './contexts/ErrorHandlerContextProvider'

// does not work
import { ErrorHandler } from '.'

由于禁用的导入工作,我们知道 impl 文件的默认导出工作。但是您的索引没有默认导出(这对于 npm 来说似乎是不礼貌的,但您确实如此)。这告诉我要么是测试文件错误地导入了 impl,要么是桶文件。 (我认为索引不太可能导出 impl 错误。)

您的所有其他进口、出口和申报在随机检查时似乎都是正确的。

所以这里有一堆想法:

  • 尝试使用实际的文件名,而不仅仅是from '.'
  • 桶中没有 React,所以尝试将 index.tsx 重命名为 index.ts
  • 确认您的测试设置在默认文件扩展名和默认文件名方面使用与应用代码相同的设置

如果这些都没有,请尝试使用您的基本错误捕获技能来查明链条中的第一个损坏的环节。

  1. 导入后将console.log("ErrorHandler", ErrorHandler) 添加到您的索引中,然后再次运行测试并查找该日志语句以确认导入的内容与您预期的一样。
  2. 在测试文件中尝试相同的操作,检查从桶文件中导入的内容。

目标是找出在导入链的哪一步出了问题。


另外:ES6 解构与 ES6 命名的导入/导出不同,你不能混合搭配。所以,我相信这段代码不应该工作

// file1.js
export default { property: 'value' }


// file2.js
import { property } from './file1' // should fail

原因是 file1 没有命名导出,它只有一个默认导出,并且 file2 中的 import 语句不允许在导入该对象时解构该对象。 file2 中的代码应该读作:“import named export 'property' from file1”——这不起作用,因为 file1 没有命名导出。

老实说,我认为这里没有违反这一点,但请牢记这一点。


最后一个想法:不要这样组织你的测试。

  1. ErrorHandlerContextProvider 的测试文件应与提供程序的 impl 位于同一文件夹中(或嵌套在 __tests 文件夹中,根据您的喜好)。该测试套件的正确工作是测试提供者的实际 impl。
  2. 如果您甚至为 index.test.tsx 烦恼,那么该套件的正确工作是只是证明您的 npm 模块的公共 API 具有正确的形状。它没有业务测试实际功能。

即使没有必要解决问题,我也会进行此更改。但是,我会推迟进行更改,直到您准确地弄清楚根本问题是什么(并解决了它)。

【讨论】:

    猜你喜欢
    • 2018-04-17
    • 2017-01-22
    • 2020-08-23
    • 2018-11-06
    • 1970-01-01
    • 2019-05-01
    • 2017-11-28
    • 2018-01-21
    • 1970-01-01
    相关资源
    最近更新 更多