I created a typescript app using CRA, with code like this:
import { ReactComponent as Search } from './search.svg'
It ran fine, and now I want to strip this code into an npm package (library). I created this package by first running CRA again, then removing everything that did not seem relevant (ex. public folder). A simplified version of /dist looks like this:
esm/
icon/
index.d.ts
index.js
index.d.ts
index.js
This is the original icon/index.ts:
/// <reference types="react-scripts" />
import { ReactComponent as Search } from './search.svg'
export const Icons = {
Search,
}
This is the compiled icon/index.d.ts:
/// <reference types="react" /> <-- Changed for some reason??
export declare const Icons: {
Search: import("react").FunctionComponent<import("react").SVGProps<SVGSVGElement> & {
title?: string | undefined;
}>;
};
When I try to run an app that then uses this library, I get the following error:
../dist/esm/common/icon/index.js Attempted import error:
'ReactComponent' is not exported from './search.svg' (imported as 'Search').
How do I resolve this?
My original answer wasn't really clear, and it didn't consider the fact that you were using create-react-app.
Since you are using create-react-app the SVGR library is already installed and being used to process SVG files as a ReactComponent.
You can just import them directly like this:
import Search from './search.svg'
and then use it like so:
export const Component = () => {
return (
<div>
<Search />
</div>
);
}
You import svg files as default imports, without brackets.
Below is an example
/// <reference types="react-scripts" />
import Search from './search.svg'
export const Icons = {
Search,
}
Related
I hope someone can tell me where I am going wrong in trying to get usable libraries
I have created a NPM project using create-react-app --format typescript, I then created the following structure:
|->tsconfig.json
|->package.json
|->config
|->tsconfig.base.json
|->tsconfig.cjs.json
|->tsconfig.esm.json
|->src
|->index.tsx
|->components
|->index.ts
|->ExampleComponent
|->ExampleComponent.component.tsx
|->ExampleComponent.stories.tsx
|->ExampleComponent.types.ts
|->index.ts
In this example the Example Component looks something like the following:
|->tscon
import React, { FC } from 'react';
// Contact specific icons
import Container from 'react-bootstrap/Container';
// Footer Properties
import { ExampleProperties } from './ExampleComponent.types';
export const ExampleComponent: FC<ExampleProperties> = ({ text }) => {
return (<Container fluid>{text}</Container>);
};
for the tsconfig files in 'config' I've lifted the Synk recommendation directly, while tsconfig.json is fairly simple like so:
{
"extends": "./configs/tsconfig.esm.json",
}
If I start the application via 'npm start' I get a website and the component correctly appears, but the issue is trying to import into another project.
I using npm link and npm link #Example/ExampleProject to bring the project in to another website and the index.tsx of that project looks like so:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { ExampleComponent } from '#Example/ExampleProject';
const container = document.getElementById('root');
if (!container) throw new Error('Failed to find the root element') const root = createRoot(container);
root.render(
<React.StrictMode>
<main role={"main"} >
<ExampleComponent/>
</main>
</React.StrictMode> );
But when it starts I am getting this error:
Module not found: Error: Can't resolve './ExampleComponent/index' in '/home/user/IdeaProjects/ExampleProject/dist/esm' Did you mean 'index.mjs'? BREAKING CHANGE: The request './Common/index' failed to resolve only because it was resolved as fully specified (probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"'). The extension in the request is mandatory for it to be fully specified. Add the extension to the request.
The only thing I can think is tsc generates src/components/index.ts as a /src/component/index.js (which I rename). But ExampleComponent has .js and .mjs files within its directory
I am having trouble with some basic module importing and exporting in react typescript. Exporting as follows:
//gameStateReducer.ts
import { Action, ActionKind, GameState } from './types';
export const gameStateReducer = (
gameState: GameState,
action: Action
): GameState => {
//yada yada yada
};
and importing as:
//index.tsx
import { gameStateReducer } from './gameStateReducer';
The error message is:
Compiled with problems:
ERROR in ./src/index.tsx 9:0-54
Module not found: Error: Can't resolve './gameStateReducer' in '/Users/REDACTED/Documents/development/react-js/wordle/src'
This was all working when I was developing the same project on stackblitz, but trouble came when I began working locally with create-react-app.
I'm having the same problem with my constants module.
I've read typescript's reference page on exports and imports, and as a matter of fact, my types and interfaces are importing and exporting just fine.
I've tried importing and exporting to default with no luck.
Gotta be something simple I'm missing here. Thanks!
The way you added import this should work. I hope your directory structure is like
src
gameStateReducer.ts
index.ts
if your gameStateReducer.ts is under different directory then you should update import path to that directory.
for example, if you have structure like below
src
anotherDirectory -> gameStateReducer.ts
index.ts
then update import statement to this
import { gameStateReducer } from './anotherDirectory/gameStateReducer';
I am creating a react component package.
I am exporting the components in a index.js file which is compiled to a index.min.js file once i build it using rollup.
But the problem is once i install the package and tried to import, vs code is not showing me the named imports as in import {A} from 'a-package'
What's i am missing?
EDIT
import React from 'react'
import a from './components/A'
import b from './components/B'
export const A = (props) => return (<a {...props} />)
export const B = (props) => return (<b {...props} />)
I solved the issue,
the issue was, since i was using rollup as a package and using the output format as umd rather than cjs
Now when i changed the format the problem is solved
I have an Icons folder and it has so many Icons.
I am trying to export them automatically, but I can't achieve it.
It is my directory map
components
ㅏ ...
ㅏIcons
ㅏ index.ts
ㅏ IconA.tsx
ㅏ IconB.tsx
ㅏ ...
ㅏ IconZ.tsx
ㅏ ...
Icons/index.ts
// I wanna avoid exporting components like this.
// export { IconA } from './IconA';
//below code doesn't work in Typescript.
const req = require.context('.', true, /\.\/.\.tsx$/)
req.keys().forEach((key: any) => {
const componentName = key.replace(/\.\/.\.tsx$/, '$1')
module.exports[componentName] = req(key).default
});
Icons/IconA.tsx
import React from 'react';
export const IconA = () => (<svg>...</svg>);
I wanna use it in another component
import { IconA, IconB, IconZ } from 'components/Icons'
I think the problem here is that because you are dynamically importing and re-exporting, it is not possible for TypeScript to guess the type of the components you are exporting, because it is unknown at compile time: your imports are just files in the eyes of the compiler.
How about using a script to generate your index.ts file to export { IconA } from './IconA'; from each of your icon files, quite similarly to what you are doing here? You could then include this script in your build process and run it everytime you compile before the typescript compiler runs
I'm using the component react-router-bootstrap and definitions from DefinitelyTyped. My problem is that the definitions downloaded does not match the component. I have created a pull request that will solve this but since I do not know when it will be patched I have to override it. I cannot just edit the type definitions file located in node_modules\#types locally because we are a team working on this project and the node_modules folder is not checked in.
How can I override type definitions? I only wan't to override LinkContainer.d file since the others files work.
Pull request:
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/16600
I tried to create a file named LinkContainer.d.ts in my typings folder that was correct but it does not get picked up. In the same folder I have a global.d.ts with interfaces that gets picked up fine.
/// <reference types="react-router-bootstrap" />
import { ComponentClass } from "react";
import { NavLinkProps } from "react-router-dom";
type LinkContainer = ComponentClass<NavLinkProps>;
declare const LinkContainer: LinkContainer;
export default LinkContainer;
Solution based on this example:
https://github.com/Microsoft/TypeScript/issues/11137#issuecomment-251755605
Add a folder called typings in root folder.
Edit tsconfig.json:
{
"compilerOptions": {
//baseUrl and paths needed for custom typings
"baseUrl": ".",
"paths": {
"*": [ "./typings/*" ]
},
...
Add a folder in the typings-folder called react-router-bootstrap (name should be identical to module) and inside that a file called index.d.ts.
In the file index.d.ts add your custom typnings or references:
import { ComponentClass } from "react";
import { NavLinkProps } from "react-router-dom";
type LinkContainer = ComponentClass<NavLinkProps>;
export const LinkContainer: LinkContainer;
When importing the module now the custom types were loaded: import { LinkContainer } from 'react-router-bootstrap';