Using styled-components results in `cannot read withConfig of undefined` - javascript

When attempting to transpile the Spacing.js file, it results in an undefined import even when styled-components was seemingly being imported and used (in the same way) successfully in other files. Even when removing the styled-components babel plugin, a similar error occurs.
.babelrc
{
"presets": [["es2015", { "modules": false }], "react-native"],
"plugins": [
["styled-components", { "displayName": true }],
"react-hot-loader/babel",
"react-native-web",
"transform-decorators-legacy",
"transform-class-properties"
],
"env": {
"production": {
"plugins": [
"transform-react-inline-elements",
"transform-react-constant-elements"
]
}
}
}
Spacing.js - Code before transpilation
import React, { Component, Node } from "React";
import styled from "styled-components";
type Props = {
size: string,
color: string,
fullWidth?: boolean
};
class SpacingComponent extends Component<Props> {
render(): Node {
const { size, color, fullWidth = false } = this.props;
return <Spacing size={size} color={color} fullWidth={fullWidth} />;
}
}
const Spacing = styled.View`
height: ${props => props.size}px;
background-color: ${props => props.color || "transparent"};
width: ${props => {
return props.fullwidth ? "100%" : props.size + "px";
}};
`;
export default SpacingComponent;
Generated code for importing and resolving styled-components
Generated code for using the styled-components library (v3.2.5)
The resulting error
Another example can be seen when removing the styled-components babel plugin from the babelrc, thus the withConfig is not added.
Generated error with no styled-components babel plugin
Generated code making this error
Is babel or webpack adding .default when it doesn't need to, if so, how could I investigate why?

try doing styled(View) instead of styled.View

Not sure if this is going to be helpful to anyone but for me the same error was triggered like this style.something and fixed using an html element eg style.span

Related

Can't load Expo Vector Icons in Nextjs

I have tried a lot of different ways to do this, with absolutely zero luck, over multiple days.
I am trying to use Solito Nativebase Universal Typescript repo to do this:
https://github.com/GeekyAnts/nativebase-templates/tree/master/solito-universal-app-template-nativebase-typescript
I have read, and tried everything on this page at least a dozen times:
https://github.com/GeekyAnts/nativebase-templates/issues/43
My current next.config.js file looks like this:
/** #type {import('next').NextConfig} */
const { withNativebase } = require('#native-base/next-adapter')
const withImages = require('next-images')
const { withExpo } = require('#expo/next-adapter')
const withFonts = require('next-fonts')
module.exports = withNativebase({
dependencies: [
'#expo/next-adapter',
'next-images',
'react-native-vector-icons',
'react-native-vector-icons-for-web',
'solito',
'app',
],
plugins: [
[withFonts, { projectRoot: __dirname }],
withImages,
[withExpo, { projectRoot: __dirname }],
],
nextConfig: {
images: {
disableStaticImages: true,
},
projectRoot: __dirname,
reactStrictMode: true,
webpack5: true,
webpack: (config, options) => {
config.resolve.alias = {
...(config.resolve.alias || {}),
'react-native$': 'react-native-web',
'#expo/vector-icons': 'react-native-vector-icons',
}
config.resolve.extensions = [
'.web.js',
'.web.ts',
'.web.tsx',
...config.resolve.extensions,
]
return config
},
},
})
I have also tried using #native-base/icons, again, no luck.
My end use case is this:
export const Cart = (props: IIconStyles) => {
return (
<Icon
as={FontAwesome5}
name="shopping-cart"
size={props.size ? props.size : 6}
color="gray.200"
/>
)
Theoretically it SHOULD show a shopping cart, but instead, this is what I see:
So clearly there's some font issue or other issue that is preventing it from loading in the actual SVG.
I can't figure out what this is - I've tried rewriting my _document.tsx file like this:
https://docs.nativebase.io/nb-icons
I've tried adding this to my next.config.js:
config.module.rules.push({
test: /\.ttf$/,
loader: "url-loader", // or directly file-loader
include: path.resolve(__dirname, "node_modules/#native-base/icons"),
});
When I try to do something like this:
import fontsCSS from '#native-base/icons/FontsCSS';
in my _document.tsx file, I get the following error:
Module not found: Can't resolve '#native-base/icons/lib/FontsCSS'
Despite the fact that I've got #native-base/icons installed in my package.json, as well as having it in my Babel file per the instruction link above.
How do I get vector icons to work in Next?
Note, this is specifically Next/Expo/React Native
You can read more about setup of next-adapter-icons here.
I got it working with following approach,
next.config.js
const { withNativebase } = require("#native-base/next-adapter");
const path = require("path");
module.exports = withNativebase({
dependencies: ["#native-base/icons", "react-native-web-linear-gradient"],
nextConfig: {
webpack: (config, options) => {
config.module.rules.push({
test: /\.ttf$/,
loader: "url-loader", // or directly file-loader
include: path.resolve(__dirname, "node_modules/#native-base/icons"),
});
config.resolve.alias = {
...(config.resolve.alias || {}),
"react-native$": "react-native-web",
"react-native-linear-gradient": "react-native-web-linear-gradient",
"#expo/vector-icons": "react-native-vector-icons",
};
config.resolve.extensions = [
".web.js",
".web.ts",
".web.tsx",
...config.resolve.extensions,
];
return config;
},
},
});
pages/_document.js
import React from 'react';
import { DocumentContext, DocumentInitialProps } from 'next/document';
import { default as NativebaseDocument } from '#native-base/next-adapter/document'
// Icon Font Library Imports
import MaterialIconsFont from '#native-base/icons/FontsCSS/MaterialIconsFontFaceCSS';
import EntypoFontFaceCSS from '#native-base/icons/FontsCSS/EntypoFontFaceCSS';
const fontsCSS = `${MaterialIconsFont} ${EntypoFontFaceCSS}`;
export default class Document extends NativebaseDocument {
static async getInitialProps(ctx) {
const props = await super.getInitialProps(ctx);
const styles = [
<style key={'fontsCSS'} dangerouslySetInnerHTML={{ __html: fontsCSS }} />,
...props.styles,
]
return { ...props, styles: React.Children.toArray(styles) }
}
}
pages/index.tsx
import React from "react";
import { Box, Icon } from "native-base";
import Entypo from "#expo/vector-icons/Entypo";
export default function App() {
return (
<Box>
<Icon
as={Entypo}
name="user"
color="coolGray.800"
_dark={{
color: "warmGray.50",
}}
/>
</Box>
);
}
Using import like this:
import MaterialIcons from '#expo/vector-icons/MaterialIcons'
in place of:
import { MaterialIcons } from '#expo/vector-icons'
worked for me. I think this is because of the way babel/webpack handles imports in the template. I followed the steps here to setup the icons.
Here's what that looks like on web:

ReferenceError: ResizeObserver is not defined:Gatsby with nivo

I use #nivo/pie with "gatsby": "^3.13.0".
But I got an error when I gatsby build.
WebpackError: ReferenceError: ResizeObserver is not defined
Nivo's version is "#nivo/pie": "^0.79.1".
I have no idea to solve it. I would be appreciate if you could give me some advice.
And here is the React code using nivo's pie chart.
PieChart.tsx
import React from 'react'
import { ResponsivePie } from '#nivo/pie'
const PieChart: React.FC = ({ data }) => {
return (
<>
<div>
<ResponsivePie
data={data}
margin={{ top: 30, right: 80, bottom: 70, left: 80 }}
borderColor={{
from: 'color',
modifiers: [
[
'darker',
0.2,
],
],
}}
arcLabelsTextColor={{
from: 'color',
modifiers: [
[
'darker',
2,
],
],
}}
fill={[
{
match: {
id: 'ruby',
},
id: 'dots',
},
]}
legends={[
{
anchor: 'bottom-right',
direction: 'column',
justify: false,
translateX: 0,
translateY: -1,
},
]}
/>
</div>
</>
)
}
export default PieChart
===================================================================
I could fix it after I updated gatsby-node.js. But I got another error WebpackError: Minified React error #130;. And I could fix it by this final code. There's no build error.
PieChart.tsx
import React from 'react'
import { ResponsivePie } from '#nivo/pie'
const PieChart: React.FC = ({ data }) => {
return (
<>
{typeof window !== 'undefined' && ResponsivePie &&
<ResponsivePie
data={data}
...
/>}
</>
)
}
export default PieChart
Thank you.
Try using a null loader on Gatsby's SSR. In your gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /#nivo\/pie/,
use: loaders.null(),
},
],
},
})
}
}
Normally this kind of issue (gatsby develop OK vs gatsby build KO) are related to webpack's bundling on the server (Server-Side Rendering), especially when dealing with third-party dependencies that interact with the window or other global objects (such as document) like chart modules do. This happens because when you run gatsby build your code is interpreted by the Node server, where there's no window available yet. On the other hand, gatsby develop is interpreted by the browser, where there is.
With this approach, you are adding a dummy loader (null) to webpacks to load the dependency on the client-side, where the window is available.
Keep in mind that test: /#nivo\/pie/ is a regular expression (that's why is between slashes, /) that tests the node_modules folder so ensure that /#nivo\/pie/ is a valid path.

MUI5 not working with jest - SyntaxError: Cannot use import statement outside a module

Reproducible repo: https://github.com/hutber/cannotusestatement
What is more worrying is: https://codesandbox.io/s/vigilant-bartik-bmz8x in the sandbox the tests pass. However if you checkout the above repo, which was imported into this sandbox it will not pass locally.
I have no doubt that the issue is my jest does not compile the node_modules that would be needed for running my tests. But I am at a loss now on how to get it working.
I would simply like to be able to run the tests. They do not run currently
test
import React from 'react'
import { renderWithThemeProvider, screen } from 'test-utils'
import { Select } from './Select'
it('renders correctly', () => {
const tree = renderWithThemeProvider(<Select id="testSelect"></Select>)
expect(tree).toMatchSnapshot()
})
jest.config.js
module.exports = {
roots: ['<rootDir>', './src'],
moduleDirectories: ['<rootDir>', 'node_modules/', './src'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
testEnvironment: 'jsdom',
testMatch: ['**/*.test.(ts|tsx)', '**/__tests__/*.(ts|tsx)'],
moduleNameMapper: {
// Mocks out all these file formats when tests are run
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'identity-obj-proxy',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'app-config': '<rootDir>/app-config/default',
'^#components(.*)$': '<rootDir>/src/components$1',
'^#themes(.*)$': '<rootDir>/src/themes$1',
},
coverageThreshold: {
global: {
statements: 50,
},
},
}
babel.config.js
module.exports = {
presets: ['#babel/preset-env', '#babel/preset-react'],
env: {
test: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
[
'babel-plugin-transform-imports',
'#babel/plugin-proposal-class-properties',
'transform-es2015-modules-commonjs',
'babel-plugin-dynamic-import-node',
'babel-plugin-styled-components',
],
},
},
}
package.json
"test": "jest --watchAll=false",
yarn test
(base) hutber#hutber:/var/www/target/component-library$ yarn test src/components/Select/Select.test.tsx
yarn run v1.22.17
$ jest --watchAll=false src/components/Select/Select.test.tsx
FAIL src/components/Select/Select.test.tsx
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/var/www/target/component-library/node_modules/#mui/material/styles/styled.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { createStyled, shouldForwardProp } from '#mui/system';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import React from 'react'
> 2 | import styled from '#mui/material/styles/styled'
| ^
3 |
4 | import MuiSelect, { SelectProps as MuiSelectProps } from '#mui/material/Select'
5 | import InputLabel from '#mui/material/InputLabel'
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/components/Select/Select.tsx:2:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.272 s
import React from 'react'
import styled from '#mui/material/styles/styled'
import MuiSelect, { SelectProps as MuiSelectProps } from '#mui/material/Select'
import InputLabel from '#mui/material/InputLabel'
import MenuItem from '#mui/material/MenuItem'
import MuiFormControl from '#mui/material/FormControl'
interface ISelect extends MuiSelectProps {
id: string
label?: string
options?: { text: string; option: string }[]
}
const FormControl = styled(MuiFormControl)`
color: #fff;
border-radius: 30px;
width: 180px;
`
export const Select: React.FC<ISelect> = ({ label, id, children, options, ...props }) => {
return (
// #ts-ignore
<FormControl fullWidth hiddenLabel>
{label && (
<InputLabel id={`input_${id}`} shrink={false}>
{label}
</InputLabel>
)}
<MuiSelect id={id} {...props}>
{options && options.map(({ text, option }: { text: string; option: string }) => <MenuItem value={option}>{text}</MenuItem>)}
{children && children}
</MuiSelect>
</FormControl>
)
}
export default Select
First you have two exports in your Select.tsx file. Just use the default export, so change line 20 to:
const Select: React.FC<ISelect> = ({ label, id, children, options, ...props }) => {
Then in your Select.test.tsx file change to:
import Select from './Select'
Finally to fix the import issue change your code in Select.tsx to:
import { styled } from '#mui/material'
This is a fairly common issue as can be seen here.

React-Image-Annotate - SyntaxError: Cannot use import statement outside a module

I'm trying to use react-image-annotate but it's giving me this issue when I first try to set it up.
And here's how I'm using it:
import React from 'react'
import ReactImageAnnotate from 'react-image-annotate'
function ImageAnnotator() {
return (
<ReactImageAnnotate
selectedImage="https://images.unsplash.com/photo-1561518776-e76a5e48f731?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
// taskDescription="# Draw region around each face\n\nInclude chin and hair."
// images={[
// { src: 'https://example.com/image1.png', name: 'Image 1' },
// ]}
// regionClsList={['Man Face', 'Woman Face']}
/>
)
}
export default ImageAnnotator
I'm using Next.js if that matters
UPDATE 1
I tried using this babel plugin as suggested by Alejandro Vales. It gives the same error as before. Here's the babel key in my package.json:
"babel": {
"presets": [
"next/babel"
],
"plugins": [
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"#babel/plugin-transform-modules-commonjs",
{
"allowTopLevelThis": true
}
]
]
}
I would say that the issue relies in the library itself by what they replied in here (similar bug) https://github.com/UniversalDataTool/react-image-annotate/issues/90#issuecomment-683221311
Indeed one way to fix it I would say is adding babel to the project so you can transform the imports in your project to require automatically without having to change the code on your whole project.
This is the babel package you are looking for https://babeljs.io/docs/en/babel-plugin-transform-modules-commonjs
Another reason for this could be an outdated version of your package, as some people report to have this fixed after using a newer version of Create React App (https://github.com/UniversalDataTool/react-image-annotate/issues/37#issuecomment-607372287)
Another fix you could do (a little crazier depending on your resources) is forking the library, creating a CJS version of the lib, and then pushing that to the library, so you and anybody else can use that in the future.
I got a tricky solution!
Problem is that react-image-annotate can only be imported in client-side(SSR got error for import keyword)
So, let react-image-annotate in Nextjs be imported only in client side
(https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr)
in Next Page that needs this component, You can make component like this
import dynamic from "next/dynamic";
const DynamicComponentWithNoSSR = dynamic(() => import("src/components/Upload/Annotation"), { ssr: false });
import { NextPage } from "next";
const Page: NextPage = () => {
return (
<>
<DynamicComponentWithNoSSR />
</>
);
};
export default Page;
Make component like this
//#ts-ignore
import ReactImageAnnotate from "react-image-annotate";
import React from "react";
const Annotation = () => {
return (
<ReactImageAnnotate
labelImages
regionClsList={["Alpha", "Beta", "Charlie", "Delta"]}
regionTagList={["tag1", "tag2", "tag3"]}
images={[
{
src: "https://placekitten.com/408/287",
name: "Image 1",
regions: [],
},
]}
/>
);
};
export default Annotation;

Distributing React UI Library with styled components

I am a junior developer who just started working in a company.
I have a bit of experience in React and could not solve the current situation.
The situation i am having a trouble with is that when I import from the library that I have distributed in npm, my React project cannot recognize the styled components.
I get this error on my project.
enter image description here
I have researched and realized that the babel needs more options such as using
"babel-plugin-styled-components" option.
Unfortunately, this did not work after using the command and distributed with the commands
yarn build == webpack --mode production
Is there anyway that I can use styled-components library??
thank you!
P:S: I think I need to put more information.
Many people thankfully answered my question but I tried them and I got an another error.
enter image description here
P.S:
My file structure:
enter image description here
My code of Button
export const StyledButton = styled.button`
background-color: white;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0.5em 1em;
padding: 0.25em 1em;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`;
export default class Button extends React.Component {
constructor(props) {
super(props);
console.log("Props:", props);
}
render() {
return (
<div>
<StyledButton>{this.props.children}</StyledButton>
{/* <button> {this.props.children} </button> */}
</div>);
}
}
My index.js of Button
import Button from "./Button";
export default Button;
My index.js of src folder
export * from "./components";
My babel.config.js
module.exports = function BabelConfigJS(api) {
api.cache(true);
const presets = ["#babel/preset-env", "#babel/preset-react"];
const plugins = [
"styled-components",
[
"#babel/plugin-transform-runtime",
{
corejs: 2,
helpers: true,
regenerator: true,
useESModules: false,
},
],
[
"#babel/plugin-proposal-class-properties",
{
loose: true,
},
],
];
return {
sourceType: "unambiguous",
presets,
plugins,
};
};
PS: Error code
enter image description here
enter image description here
enter image description here
The error (which really is just an Eslint complaint) does not refer to using styled-components at all!
It's just saying components should be in PascalCase, not camelCase as you have now.
That is, instead of <styledComponent />, it'd be <StyledComponent />.
You just need to change the component name to be Uppercased, it has nothing to do with babel, etc.
// not <styledButton/>
<StyledButton/>
It is a requirement from React as in JSX lower-case tag names are considered to be HTML tags.

Categories