I couldn't import from src folder in expo react - javascript

I'm using expo-cli.
I import a module from the folder 'src' (i created this folder), if open in web this work perfectly, but if open in android not found this.
I try use the absolute path, the Babel Resolver module and nothing work.
Project:
-assets
-node_modules
-src
-components
-screens
-HomeScreen.js
-services
-Webservices.js
-styles
-utils
-App.js
...
Screen file:
...
import WebServices from '../services/WebServices';
export default class HomeScreen extends React.Component {
...
File to import:
const axios = require('axios');
var url = 'https://randomuser.me/api/';
var WebServices = {
getUser: function(){
return axios.get(url);
}
}
export { WebServices as default };
Error:
Android Bundling failed 5347ms
Unable to resolve module ../services/WebServices.js from C:\Users\jalvarez\Proyectos\AppPruebas\src\screens\HomeScreen.js:
None of these files exist:
* src\services\WebServices.js(.native|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json)
* src\services\WebServices.js\index(.native|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json)
5 | import { createNativeStackNavigator } from '#react-navigation/native-stack';
6 |
> 7 | import WebServices from '../services/WebServices.js';
| ^
8 |
9 | export default class HomeScreen extends React.Component {
enter image description here

Installing Typescript and babel-plugin-root-import modules and with this config in babel.config.js and tsconfig.json work for me in android and web.
balbel.config.js:
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
'babel-plugin-root-import',
{
root: __dirname,
rootPathPrefix: '~',
rootPathSuffix: './src',
},
]
]
};
};
In tsconfig.json add:
"rootDir": "./"
For import:
import WebServices from '~/services/webservices';

Related

How to share Vite config in monorepo?

I am trying to make monorepo using Turborepo. I have a lot of Vue projects there and I need to share Vite config across all applications. Here's how I'm trying to achieve this.
I have package named #monorepo/configs:
packages/
configs/
package.json
index.ts
vite.config.base.ts
package.json:
{
"name": "#monorepo/configs",
"version": "0.0.1",
"private": true,
"type": "module",
"main": "index.ts",
"types": "index.ts",
"files": [
"./src/tsconfig.base.json",
"./src/vite.config.base.js"
]
}
vite.config.base.ts:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
// regular config
export const ViteConfigBase = defineConfig({
resolve: {
alias: {
// some aliases
}
}
})
index.ts:
export { ViteConfigBase } from './vite.config.base'
And in the other application's vite.config.ts:
import { fileURLToPath, URL } from 'node:url'
import { ViteConfigBase } from '#monorepo/configs/src/vite.config.base' // notice import from 'src'
import { defineConfig, mergeConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
export default defineConfig(mergeConfig(
ViteConfigBase,
{
plugins: [vue()],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
}
))
Here I import ViteConfigBase as a file from 'src' folder and this is the error that I get after npm run dev:
> #monorepo/sandbox#0.0.0 dev
> vite
failed to load config from C:\Users\user\Desktop\Code\Personal\monorepo\apps\Sandbox\vite.config.ts
error when starting dev server:
Error [ERR_REQUIRE_ESM]: require() of ES Module C:\Users\user\Desktop\Code\Personal\monorepo\packages\Config\src\vite.config.base.js from C:\Users\user\Desktop\Code\Personal\monorepo\apps\Sandbox\vite.config.ts not supported.
Instead change the require of vite.config.base.js in C:\Users\user\Desktop\Code\Personal\monorepo\apps\Sandbox\vite.config.ts to a dynamic import() which is available in all CommonJS modules.
If I change import from 'src' folder to import from index, like this:
import { fileURLToPath, URL } from 'node:url'
import { ViteConfigBase } from '#monorepo/configs' // <-- here
import { defineConfig, mergeConfig } from 'vite'
// other config...
Then the error will be this:
> #monorepo/sandbox#0.0.0 dev
> vite
failed to load config from C:\Users\user\Desktop\Code\Personal\monorepo\apps\Sandbox\vite.config.ts
error when starting dev server:
C:\Users\user\Desktop\Code\Personal\monorepo\packages\Config\index.ts:1
export { ViteConfigBase } from './src/vite.config.base'
^^^^^^
SyntaxError: Unexpected token 'export'
OOokkay, I've seen it before. Let's try "type": "module" in package.json. Now that's the error:
> #monorepo/sandbox#0.0.0 dev
> vite
failed to load config from C:\Users\user\Desktop\Code\Personal\monorepo\apps\Sandbox\vite.config.ts
error when starting dev server:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for C:\Users\user\Desktop\Code\Personal\monorepo\packages\Config\index.ts
And this is where I'm stuck. I need those files to be .ts for sure (and I'm not sure if they would work if I change extention to .js).
I could also easily fix this by just adding the build step, but I don't think it is that necessary and there should be the way around. The build step will add a lot of overhead to development process and the code itself. I've tried it and the dist folder was around ~4Mb for no reason. Also, I won't be able to use "Go to definition" feature in this case, and last but not least, it has to be rebuilt after every change, so I really wish to avoud this step and just use raw config files everywhere.
If you using Turborepo, how about this way?
/
├── apps
| ├── app1
| | ├── src
| | ├── package.json
| | └── vite.config.ts
| └── app2
| ├── src
| ├── package.json
| └── vite.config.ts
├── packages
| └── viconfig
| ├── index.js
| └── package.json
// apps/app1/package.json
{
"name": "app1",
"devDependencies": {
"viconfig": "workspace:*",
"vite": "4.0.0"
}
}
// apps/app1/vite.config.ts
import { defineConfig } from "vite";
import customConfig from "viconfig";
export default defineConfig(() => {
return {
...customConfig,
};
});
// packages/viconfig/index.js
import path from "node:path";
export default {
resolve: {
alias: {
"#": path.resolve(process.cwd(), "src"),
},
},
};
// packages/viconfig/package.json
{
"name": "viconfig",
"main": "index.js",
"type": "module",
"types": "index.js"
}

TypeScript and Rollup: "Cannot read properties of undefined (reading 'v4')" when using the uuid package

I am trying to use the uuid package in my TypeScript project, but I am encountering an error when I try to use the v4 method. The error message is: "Cannot read properties of undefined (reading 'v4')".
I have also included the #rollup/plugin-node-resolve, #rollup/plugin-commonjs, and #rollup/plugin-replace plugins in my rollup.config.js file in order to handle the uuid package, which is a Node.js-style package.
Here is my rollup.config.js file:
import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import image from "#rollup/plugin-image";
import json from "#rollup/plugin-json";
import commonjs from "#rollup/plugin-commonjs";
import nodeResolve from "#rollup/plugin-node-resolve";
import builtins from "rollup-plugin-node-builtins";
import replace from "#rollup/plugin-replace";
export default [
{
input: "src/index.ts",
output: {
file: "dist/bundle.js",
format: "cjs",
},
external: ["uuid"],
plugins: [
image(),
terser(),
postcss(),
nodeResolve(),
commonjs(),
replace({
require: "function(){}",
preventAssignment: true,
}),
builtins(),
typescript({
tsconfig: "tsconfig.json",
}),
json(),
],
},
];
In this project, I am using web components for my application. I am using the uuid package to generate unique IDs for these components, but I am encountering an error when I try to use the v4 method.
In one of my web component class, an example usage is like this:
import {v4 as uuidv4} from "uuid"
export class ExampleWebComponent extends HTMLElement{
...
private setInitialAttributes() {
this.setAttribute("customer-id", uuidv4());
}
...
connectedCallback() {
if (this.shadowRoot) {
this.setInitialAttributes();
}
}
}
And then I import this web component at App.ts file:
import { ExampleWebComponent } from "./web-components/ExampleWebComponent";
And define it to window.customElements:
function defineWebComponents() {
window.customElements.define("example-web-component", ExampleWebComponent);
}
export default defineWebComponents;
and I finally call the defineWebComponents function in index.ts file:
import defineWebComponents from "./App";
defineWebComponents();
const newComponent = document.createElement("example-web-component");
console.log(newComponent.getAttribute("customer-id");
I was expecting the v4 method to generate a new UUID. I was also expecting the #rollup/plugin-node-resolve, #rollup/plugin-commonjs, and #rollup/plugin-replace plugins to correctly handle the uuid package and allow me to use it in my TypeScript code.

Cannot find module with absolute import Next+TS+Jest

I am using absolute imports and
testing a component with Context Provider in a NextJS project.
I have set this up according to jest setup
TEST:
import { render, screen } from 'test-util';
import { Sidebar } from '#/components/Sidebar/Sidebar';
test('if it has a brand image', () => {
render(<Sidebar />);
const brandLogo = screen.getByAltText('logo');
expect(brandLogo).toBeInTheDocument();
});
Here is my test-util.tsx in the root folder.
import React, { FC, ReactElement, ReactNode } from 'react';
import { render, RenderOptions } from '#testing-library/react';
import { AuthProvider } from 'store/auth';
const AllTheProviders: FC = ({ children }) => {
return <AuthProvider>{children}</AuthProvider>;
};
const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>) =>
render(ui, { wrapper: AllTheProviders, ...options });
export * from '#testing-library/react';
export { customRender as render };
This is my jest.config.js in the root folder
// #ts-nocheck
const nextJest = require('next/jest');
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
// Handle module aliases (this will be automatically configured for you soon)
'^#/components/(.*)$': '<rootDir>/components/$1',
'^#/pages/(.*)$': '<rootDir>/pages/$1',
'^#/firebase/(.*)$': '<rootDir>/firebase/$1',
'^#/store/(.*)$': '<rootDir>/store/$1',
},
testEnvironment: 'jest-environment-jsdom',
};
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
Here is jest.setup.js in the root folder
import '#testing-library/jest-dom/extend-expect';
I get this error:
FAIL components/Sidebar/__test__/Sidebar.test.tsx
● Test suite failed to run
Cannot find module 'test-util' from 'components/Sidebar/__test__/Sidebar.test.tsx'
1 | import { Sidebar } from '#/components/Sidebar/Sidebar';
> 2 | import { render } from 'test-util';
| ^
3 |
Here is tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"#/pages/*": ["./pages/*"],
"#/components/*": ["./components/*"],
"#/features/*": ["./features/*"],
"#/firebase/*": ["./firebase/*"],
"#/store/*": ["./store/*"]
}
}
}
How to solve this issue? I want to use
import { render, screen } from 'test-util';
What works:
import { render, screen } from '../../../test-util';
import { Sidebar } from '#/components/Sidebar/Sidebar';
test('if it has a brand image', () => {
render(<Sidebar />);
const brandLogo = screen.getByAltText('logo');
expect(brandLogo).toBeInTheDocument();
});
I have a similar config, but it works for me.
Try to add moduleDirectories: ["node_modules", "<rootDir>/"]
inside your customJestConfig object.

Which Babel plugin allows me to do `import { Header, Footer } from "components"`?

I have my Next.js project set up with the following folder structure:
- src
- components
- Header
- Header.tsx
- Header.styles.ts
- index.ts ( `export { Header } from "./Header"` )
- Footer
- Footer.tsx
- Footer.styles.ts
- index.ts ( `export { Footer} from "./Footer"` )
- index.ts ( `export { Footer } from "./Footer"` and `export { Header } from "./Header"` )
I've also configured Babel with the following configuration:
{
"plugins": [
[
"module-resolver",
{
"root": ["src"],
"extensions": [".js", ".ts", ".tsx"]
}
]
]
}
This setup allows me to do the following: import { Header, Footer } from "components". I'm looking to get rid of all these index.ts files. All the index files in the component folders contain export { COMPONENT_NAME } from "./COMPONENT_NAME". And the universal index file in the component folder also contains export { COMPONENT_NAME } from "./COMPONENT_NAME", for each of the components.
How can I configure Babel to allow me to do import { Header, Footer } from "components" and have it expand this to:
import { Header } from "components/Header/Header"
import { Footer} from "components/Footer/Footer"
I'm using TypeScript so any help with how to configure this in tsconfig.json would be appreciated!

Can't import React component on server-side Next.js

I'm trying to import a very simple component from a library into a Next.js app.
I have stripped down my library to the bare minimum. It contains the following src/components/index.js:
import React from 'react'
const Container = ({ children }) => <div>{children}</div>
export { Container }
In my Next.js app, I created a pages/index.js that contains the following:
import React from 'react'
import { Container } from 'mylib'
class HomePage extends React.Component {
render() {
return <Container>Hello</Container>
}
}
export default HomePage
mylib is a local npm package which I have installed in my Next.js app using npm i ../mylib. It has a standard webpack config:
const path = require('path')
module.exports = {
entry: {
components: './src/components/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
libraryTarget: 'commonjs2'
},
mode: "production",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
}
],
},
};
and then the package.json points to dist/components.js as the main file.
The following does work:
In my Next.js app, replace return <Container>Hello</Container> with return <div>Hello</div> (while keeping the import { Container } in place)
Refresh the page in the server (I'm running Next's dev server)
Restore the use of <Container> (the opposite of step 1)
Save the file --> hot-reload in the browser with the Container properly displayed (I added a className to be sure)
At this point, if I refresh the browser, I get the following error:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
which suggests I made a bad import/export, but I don't know where. And the error only occurs on the server-side.
What did I do wrong?
Container should be a default export, so this:
import React from 'react'
const Container = ({ children }) => <div>{children}</div>
export { Container }
should be this:
import React from 'react'
const Container = ({ children }) => <div>{children}</div>
export default Container
You could also one-line the Container component like this:
import React from 'react'
export default Container = ({ children }) => <div>{children}</div>

Categories