No stylesheet generated by styled-components on nwb reusable component - reactjs

I've built a reusable react component through nwb new react-component fade-preloader called FadePreloader which uses styled-components, its published on npm so I can use it on other projects, but when its imported as a module its styles are never added to the DOM. The following provides more details about the nwb component.
src folder is:
src/
FadePreloader.js
FadePreloader.Styled.js
index.js
FadePreloader.js:
import React, {Component} from "react"
class FadePreloader extends Component {
// logic code
}
export default FadePreloader
FadePreloader.Styled.js:
import styled from "styled-components"
import FadePreloader from "./FadePreloader"
const FadePreloader_Styled = styled(FadePreloader)`
// css here
`
export default FadePreloader_Styled
index.js:
// just import the styled-componet and re-export it
import FadePreloader from "./FadePreloader.Styled"
export default FadePreloader
I have the default configuration in package.json provided by nwb:
FadePreloader is published on npm so I added it on other project (through yarn add fade-preloader) and use it like this:
App.jsx on other project:
// lots of imports here
import FadePreloader from "fade-preloader"
class App extends Component {
render() {
return(
<div>
<FadePreloader />
</div>
)
}
}
export default App
The FadePreloader component is rendered in the DOM and its class attribute has the className generated by styled-components as espected but the stylesheet is never added to the DOM, no <style> element is present causing an unstyled FadePreloader rendered. What's wrong?

I've found a solution coming from the official spectrum channel of styled-components, see here.
What I had to do was to follow this which basically says that styled-components dependency needs to be moved from dependencies to devDependencies and peerDependencies in package.json. I'm not sure the reason but it seems to be to avoid some unexpected reason that is generated by duplicated direct dependency of styled-components.

Related

Reexporting JSS via index.js causing unwanted rerenders in unrelated components

I have a large codebase where Material UI with it's JSS are being used.
jss/
a.js Default or named export `astyle`
b.js Default or named export `bstyle`
index.js - Re-exports the JSS
All other files import like import { astyle } from './jss'
ComponentA.jsx - contains `import { astyle } from './jss'`
ComponentB.jsx - contains `import { bstyle } from './jss'`
App.jsx - imports ComponentA and ComponentB
Updating a.js causes ComponentB to re-render as well, is there any way I can tell webpack to not reload the entire jss/index.js?
Components work fine
componets/
ComponentC.jsx - default or named export
ComponentD.jsx - default or named export
index.js - Re-exports the components
App.jsx - import { ComponentC, ComponentD } from './components'
Updating ComponentC will not re-render ComponentD or components/index.js
I'm looking for the least disruptive solution and would prefer not to import all the styles directly by file name getting rid of the jss/index.js
Here is the demo repo and is based on the example from the fast refresh repo here
Turns out simply upgrading to webpack 5 fixes it, you can view the updated repo at this branch

what does babel-plugin-named-asset-import do

Ok I've looked everywhere and there is no documentation on this Babel module
--babel-plugin-named-asset-import
can someone please explain what it is for and how it works.
Looks like its purpose is to import named exports from non JS/CSS assets. Currently, within the CRA, it appears to only be implemented for svg assets. The goal is to offer another way to import SVGs as React components versus the standard import as a url that needs to be applied to an img element.
Without plugin (default import)
import * as React from 'react';
import logo from './logo.png'; // import file as a url
function Header() {
return <img src={logo} alt="logo" />;
}
export default Header;
With plugin (named import)
import * as React from 'react';
import { ReactComponent as Logo } from './logo.svg'; // import file as a React component
function Header() {
return <Logo />;
}
export default Header;
Update
Going deeper, it appears that the plugin aids in importing svg files in the following ways:
import logo from "logo.svg"; // default import
import { logoUrl } from "logo.svg"; // named import
import { ReactComponent as Logo } from "#svgr/webpack?-svgo!logo.svg"; // ReactComponent import
The CRA specifically targets svg file formats as shown in their test suites. As to whether or not it supports other non-js files, not likely (especially since the babel plugin is only utilized once in the CRA webpack config).
As mentioned in the svgr docs:
SVGR can be used as a webpack loader, this way you can import your SVG directly as a React Component.
This particular plugin aims to import any svg file as the default export.
Please note that by default, #svgr/webpack will try to export the React Component via default export if there is no other loader handling svg files with default export.
Whereas the CRA appears to utilize file/url loader for the default/named exports and specifically maps a ReactComponent named export to the svgr webpack plugin.

React won't import my module "Module not found: Can't resolve "

React is not resolving my component import into my YouTubeApp.js.
It seems silly, i have other components in my react app that I'm able to import with no issues but this one in particular i can't get it imported.
Github: https://github.com/JAlonsoHdz/React_UnsplashClientApp/tree/master/src/components
Additional context, YouTubeApp.js is currently imported in my index.js with no issues. I'm using react routing imported in the index.js and links and the route links sucessfully to YouTubeApp.js. The problem arise whenver I try to import ANY component into YouTubeApp.js i get the Cannot resolve 'component name' error, without any imports the component YouTubeApp.js works fine.
I have validated the correct path, the name of the component.
YouTubeApp.js
import React from 'react';
import Other from './components/other';
class YouTubeApp extends React.Component {
render() {
return (<p>test</p>
);
}
}
export default YouTubeApp;
And this is my component I'm trying to import:
import React from 'react';
class Other extends React.Component {
render() {
return (
<div clasNames="ui container">test!</div>
);
}
}
export default Other;
I need to nest at least a few levels down more components but this issue blocking.
Looking at your GitHub repository, it appears that YouTubeApp.js and other.js are both in the "components" directory. Therefore when in YouTubeApp.js (or any other component in your "components" directory) your import should be:
import Other from './other';

Importing React Component from bundled file

I have a bunch of React components in a folder and I can import each one individually like this:
import Component1 from '../components/component1/component1';
import Component2 from '../components/component2/component2';
Using the components like this works fine. However, when I bundle all the components using Webpack, the following code returns an empty object when I try to import the component.
import Component1 from '../dist/bundle.js';
I can't render this component. How do I export the components when bundling files?
Simply put you cannot import any modules from a bundle.
You need to include this code inside the source and then bundle it together
Actually you can do that. In my situation I needed react components in backbone application so what I did:
In react exposed components that should be importable by exporting them in entry point (usually index.js) like:
import React from 'react';
import ReactDOM from 'react-dom';
import Header from './components/Header/Header';
export {
React,
ReactDOM,
Header
};
Made my bundle output as library:
output: {
path: /some/path/of/your/lib,
library: 'reactapp',
libraryTarget: 'umd',
filename: `app${jsExtension}`,
},
Then bind name to file path in requirejs config:
reactapp: '/some/path/of/your/lib/app.js'
Then in code I can import that bundle as reactapp like:
define(["reactapp"], function(reactapp) {
// reactapp is object containing React, ReactDOM, Header
});

import App from './App';

I am trying react based on create-react-app. I'm new to react.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById('root')
);
./App in import App from './App'; is not clear to me when and where is this created, is this done by babel?
file strucutre
my-app/
README.md
node_modules/
package.json
.gitignore
public/
favicon.ico
index.html
src/
App.css
App.js
App.test.js
index.css
index.js
logo.svg
App.js
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div>myComponent</div>
)
}
}
export default App;
tl;dr
No, it is not done by Babel, instead it is done by create-react-app package.
All the files and folders in that folder are created automatically when you run,
create-react-app your-new-app-name
import App from './App'
The above line is used for importing the class you have written in the file App.js under the same directory.
Next, the difference between,
import App from './App'
and
import App from 'App'
Use the first if you want to import any user defined files and second for importing packages. As Shubham Khatri mentioned, for importing files, it is technically same if you did or did not use .js extension.
The longer version
create-react-app is a starter kit for people who are new to React or for who are lazy enough to build an app from scratch. What create-react-app does is, it will give you a minimal running React app with a solid folder structure. As given in their documentation, you can install that globally by giving,
npm install -g create-react-app
After this whenever you want to create a new app, what you want to do is,
create-react-app your-new-app-name
This will automatically generate a folder with all the files you mentioned.
Within the folder when you open the file public/index.html, you can see a line
<div id="root"> </div>
And on the src/index.js, you can find,
ReactDOM.render(
<App />,{}
document.getElementById('root')
);
If you are familiar with javascript, you may know that document.getElementById('root') is used to match any tag in HTML with ID as root. So the above snippet means that, they are rendering the <App> component of react to div with ID root. This is how React communicates with HTML page.
Rather that writing all the component codes in a single file, it is a good standard to write each components in different files. Here, App.js is a component that basically renders the text myComponent. For using this component in other files, you have to do two things.
Export the component from the file where it is defined. (export default App;)
Import the component to the file where it is used. (import App from './App')
General syntax for import is,
import className, { functionName } from 'packageName'
or
import className, { functionName } from './path-to-file/fileName'
Note: It is that ./ which tells the compiler whether to look on to node_modules folder or the path you mentioned. Use that strictly when you need to import user defined files.
Hope this helps!
When you import your Component like
import App from './App';
It will import your file App.js that is present in the same direcotry as index.js
In webpack configuration we specify which types of files babel needs to build and there if we specify .js or .jsx, it takes by default the extension of the file when we import it. we do not explicitly mention it. You can change your immport to be like
import App from './App.js';
which is technically the same.
The create-react-app npm package makes use of webpack to build your code which you can see from the package/react-scripts/package.json in the github directory

Resources