How to import SVG's in nextjs - javascript

I'm migrating my react website to nextjs. I have one assets folder at the root which contains lots of svgs and I have one constants.js file where I'm importing all the SVG's as ReactComponent. I would like to know how to convert this part of code in nextjs.
Error message:
Module not found: Can't resolve '../../../assets/skills/html5.svg'
> 1 | import { ReactComponent as HTML } from "../../../assets/skills/html5.svg";
2 | import { ReactComponent as CSS } from "../../../assets/skills/css.svg";
constants.js
import { ReactComponent as HTML } from "../../../assets/skills/html5.svg";
import { ReactComponent as CSS } from "../../../assets/skills/css.svg";
export const SKILLS = [
{
name: "html",
image: HTML, // SVG Component
},
{
name: "css",
image: CSS,
},
]
Folder Structure:

You can setup SVGR into your project and add them as regular react components. Your code could end up looking something like this
export const SKILLS = [
{
name: "html",
image: <Html className="html"/>, // SVG Component
},
{
name: "css",
image: <Css className="css"/>,
},

Related

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.

Module not found Error: You attempted to import which falls outside of the project src/ directory. Relative imports outside of src/ are not supported

I am currently making a music player app on React, and am new to React js. Not sure why i'm getting this error, having been following the exact steps on the tutorial I'm watching.
The full Error Code is:
Module not found: Error: You attempted to import ../components/Player which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
You can either move it inside src/, or add a symlink to it from project's node_modules/.
For better clarity, This is the code for the Player component:
import React from 'react';
import PlayerDetails from './PlayerDetails';
function Player(props) {
return (
<div className="c-player">
<audio></audio>
<h4>Now playing</h4>
<PlayerDetails song={props.song}/>
{/*CONTROLS */}
<p><strong> Next Up:</strong> {props.nextSong.title} {props.nextSong.artist}</p>
</div>
);
}
export default Player;
And this is the Code on App.js:
import { useState } from "react";
import Player from "../components/Player";
function App() {
const [songs, setSongs]= useState([
{
title: "1",
artist: "1",
img_src: "./images/song-1.jpg/",
src: "./music/song-1.mp3"
},
{
title: "2",
artist: "2",
img_src: "./images/song-2.jpg/",
src: "./music/song-2.mp3"
},
{
title: "3",
artist: "3",
img_src: "./images/song-3.jpg/",
src: "./music/song-3.mp3"
},
{
title: "4",
artist: "4",
img_src: "./images/song-4.jpg/",
src: "./music/song-4.mp3"
}
]);
const [currentSongIndex, setCurrentSongIndex]= useState(0);
const [nextSongIndex, setnextSongIndex]= useState (currentSongIndex + 1);
return (
<div className="App">
<Player
songs= {songs[currentSongIndex]}
nextSong={songs[nextSongIndex]}
/>
</div>
);
}
export default App;
Here is the folder structure:
Appreciate your time!
I think path for your Player component is incorrect
import Player from "../components/Player";
Try this:
import Player from "./components/Player";
Your components folder should be under the src folder, then set the path carefully.

Modifying an existing file with Plop?

I’m using plop to generate components for a React-based component library. I have a directory full of Handlebars templates that are used to create new component directories, and all is working well. I also have this index.js file that acts as the entrypoint for my bundler. It’s just full of lots of imports and an export. It looks like this:
import { Badge } from './components/Badge';
import { Button, ButtonMemo } from './components/Button';
import { Column } from './components/Column';
import { ErrorBoundary } from './components/ErrorBoundary';
import { FormBasicInfo } from './components/FormBasicInfo';
import { FormLogin } from './components/FormLogin';
import { FormSignup } from './components/FormSignUp';
import { Icon } from './components/Icon';
import { Input } from './components/Input';
import { Link } from './components/Link';
import { Loader } from './components/Loader';
import { Logo } from './components/Logo';
import { Row } from './components/Row';
import { Select } from './components/Select';
import { SimpleMenu } from './components/SimpleMenu';
import { Slideshow } from './components/Slideshow';
import { Spinner } from './components/Spinner';
export {
Badge,
Button,
Column,
ErrorBoundary,
FormBasicInfo,
FormLogin,
FormSignup,
Icon,
Input,
Link,
Loader,
Logo,
Row,
Select,
SimpleMenu,
Slideshow,
Spinner,
};
When generating a new component, I would love to also add the new component to this entrypoint file. That would require adding an import line to the top block, and an export line to the bottom. Ideally it would still be alphabetically sorted, but that isn’t a hard requirement.
Is this possible?
This is how I ended up pulling it off:
In my index.js file (the one I want modified), I added two comments in the places where the inserts should take place:
…
import { PointAccountCard } from './components/PointAccountCard';
import { Card } from './components/Card';
import { SettingsPanelFooter } from './components/SettingsPanelFooter';
// COMPONENT IMPORTS
export {
…
PointAccountCard,
Card,
SettingsPanelFooter,
// COMPONENT EXPORTS
};
Then in my plopfile.js config, I added these two steps to my actions config:
module.exports = function (plop) {
plop.setGenerator('component', {
actions: [
…
{
path: '../../src/index.js',
pattern: /(\/\/ COMPONENT IMPORTS)/g,
template: 'import { {{name}} } from \'./components/{{name}}\';\n$1',
type: 'modify',
},
{
path: '../../src/index.js',
pattern: /(\/\/ COMPONENT EXPORTS)/g,
template: '\t{{name}},\n$1',
type: 'modify',
},
],
description: 'New React Component',
prompts: [
…
],
})
};
All new components are automatically added to the index.js file.

Webpack loader for .md file import for "react-markdown" npm library?

When i import a .md file , it gave me error, saying that it cannot read this particular .md file syntax,
I know there needs to be some kind of loader for it to parse the import, but when i looked online there was a loader called 'markdown-loader' which was only for marked npm package.
I am using react-markdown package to read md files
/* eslint-disable react/prefer-stateless-function */
import React, { Component } from 'react';
import ReactMarkdown from 'react-markdown';
import AppMarkdown from './posts/sample.md';
// import PropTypes from 'prop-types';
class CardDetails extends Component {
constructor() {
super();
this.state = { markdown: '' };
}
componentDidMount() {
// Get the contents from the Markdown file and put them in the React state, so we can reference it in render() below.
fetch(AppMarkdown)
.then(res => res.text())
.then(text => this.setState({ markdown: text }));
}
render() {
const { markdown } = this.state;
return <ReactMarkdown source={markdown} />;
}
}
CardDetails.propTypes = {};
export default CardDetails;
here's my markdown content sample.md
# React & Markdown App
- Benefits of using React... but...
- Write layout in Markdown!
i could not find package , i looked everywhere, do you know about the loader ?
Thankyou
Try to use raw-loader:
module.exports = {
module: {
rules: [
{
test: /\.md$/,
use: 'raw-loader'
}
]
}
}

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