I have a simple Context Provider that I want to export as a npm package.
I created my npm package using create-react-library .
I have created an index.tsx file that will be accessible when importing this npm package from another project; I am importing the Context Provider to this index.tsx, then exporting it.
When I try and run a test with the ContextProvider imported from index.tsx, the imported object is undefined (even though I can navigate to it in VS Code). However, when I import it directly from the source, it works fine. I will need to have it working from the index.tsx file in order to access it through the npm package.
Can anyone explain to me what I'm missing here?
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 run test
FAIL src/index.test.tsx ● ErrorHandlerContextProvider › is truthy
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)
This seems really suspicious:
// src/index.test.tsx
// works
// import ErrorHandler from './contexts/ErrorHandlerContextProvider'
// does not work
import { ErrorHandler } from '.'
Since the disabled import works, we know that the impl file's default export is working. But your index has no default export (which seems like bad manners for npm, but you do you). This tells me that either the test file is importing the impl wrongly, or the barrel file is. (I think it is unlikely that the index is exporting the impl wrongly.)
All your other imports, exports, and declarations seem correct on casual inspection.
So here is a grab-bag of ideas:
from '.'
index.tsx
to index.ts
If none of those does it, try using your basic error-trapping skills to pinpoint the first broken link in the chain.
console.log("ErrorHandler", ErrorHandler)
to your index after the import, then run the tests again and look for that log statement to confirm that the imported thing looks like you'd expect.The goal is to figure out at which step of the import chain things go awry.
Also: ES6 destructuring is not the same thing as ES6 named imports/exports, and you can't mix-and-match. So, I believe this code should not work :
// file1.js
export default { property: 'value' }
// file2.js
import { property } from './file1' // should fail
The reason is that file1 does not have named exports, it has only a default export, and the import statement in file2 is not permitted to destructure that object while importing it. The code in file2 should be read as: "import named export 'property' from file1" -- which will not work because file1 has no named exports.
In all honesty, I don't see a violation of this here, but it's something to keep in mind.
One final thought: don't organize your tests like this.
ErrorHandlerContextProvider
should live in the same folder as the impl of the provider (or in a nested __tests
folder, according to your preference). The proper job of that test suite is to test the actual impl of the provider.index.test.tsx
, the proper job of that suite is just to prove that the public API of your npm module has the right shape. It has no business testing the actual functionality.I would make this change even if it's not necessary to fix the problem. But, I'd hold off on making the change until after you have figured out precisely what the underlying problem is (and fixed it).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.