React styled-components not applying styles to components - reactjs

I'm trying to get used to styled-components in react. But it doesn't seem to work all the time. I'm currently using it in a project. While it works perfectly in some components, it doesn't apply the styles in some others.
Here's my code where it doesn't work.
I created the styles-components in a separate file (card.js) and folder (styles) and exported them like so;
import styled from 'styled-components/macro';
export const Title = styled.p`
font-size: 24px;
color: #e5e5e5;
font-weight: bold;
margin-left: 56px;
margin-right: 56px;
margin-top: 0;
`;
... (other components created the same way)
I then imported them in a file (index.js), in the same folder as the styles folder, containing the card.js file, where I used them like so;
import React from 'react';
import {Title, (some other components) } from './styles/card';
export default function Card({ children, ...restProps }) {
return <Container {...restProps}>{children}</Container>
}
Card.Title = function CardTitle({ children, ...restProps }) {
return <Title {...restProps}>{children}</Title>;
};
I then
I used the same method in all other styled-components files, but it doesn't work here. I'd like to know the cause, or if there's a better method of using styled-components.

Figured it out! React styled-components works perfectly when applied correctly. The problem was a typo error in my code.
I wrote
&{Picture}
when calling an earlier declared styled component instead of
${Picture}

Related

NextJS with styled-components fast refresh not working

I have a NextJS app being used with styled-components.
I have these 3 files:
Worth noting that some markups are removed for clarity sake so only the related codes are pasted.
Header.js
import {
HeaderContainer,
SearchInput,
SearchWrapper
} from './HeaderStyles';
import { Input } from '../GlobalComponents/GlobalComponents';
const Header = () => {
return (
<HeaderContainer>
<SearchWrapper>
<SearchInput type='text' placeholder='Search movie' />
</SearchWrapper>
</HeaderContainer>
);
}
export default Header;
HeaderStyles.js
import styled from 'styled-components';
import { Input } from '../GlobalComponents/GlobalComponents';
export const HeaderContainer = styled.header`
background-color: ${props => props.theme.colors.primary};
display: flex;
align-items: center;
box-sizing: border-box;
`;
export const SearchWrapper = styled.div`
flex-grow: 3;
background-color: red;
`;
export const SearchInput = styled(Input)`
background-color: yellowgreen;
`;
GlobalComponents.js
import styled from "styled-components";
export const Input = styled.input`
padding: 1rem;
`;
Attached is my
Project Structure
Note that inside HeaderStyles.js, the SearchInput is extended from Input in GlobalComponents.js
Whenever I change css properties in HeaderStyles.js, the fast refresh works just fine. However, in the case of GlobalComponents.js, I had to manually reload the page to view the changes.
If I were to put my generic Input styling into HeaderStyles, it works fine, but that isn't how I wanted to structure it. So I guess it somewhat related to the imported modules not being in the React tree or stuff like that.
I have been looking for solutions online but got no luck. Would like to know the causes and solution for this. Thanks in adv.
I think your problem about styled-component at SSR.
You can try change your pages/_document.js and your babel config.
add this codes to .babelrc
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
_document.js
https://github.com/vercel/next.js/blob/main/examples/with-styled-components/pages/_document.js
with the Next Complier on new version of next, you should only update your next.config file and _document file, and you will be all set. Babel will cause conflict with the NextJS compiler.
https://github.com/vercel/next.js/tree/canary/examples/with-styled-components
Make sure you have pages/_document.js with codes stated here.

Alternative to createGlobalStyle from styled-components that can also be importable

we are currently loading Fonts and few other global styles like this:
import { createGlobalStyle } from 'styled-components';
export default createGlobalStyle`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
And in every _app.tsx (from every project in repo) we just
import GlobalStyle from #our-company/ui;
// few other imports
const AppProviders = ({ children, messages, locale }: Props): JSX.Element => {
return (
<IntlProvider
locale={locale || 'en-GB'}
key={locale}
messages={messages[locale]}
defaultLocale="en-GB"
>
<GlobalStyle />
<DsThemeProvider
locale={locale}
>
{children}
</DsThemeProvider>
</IntlProvider>
);
};
But we noticed unnecessary font reloads caused by this GlobalStyle when clicking, for example, in checkbox elements (tried putting this in a .css and just load it and never happens again).
Any idea how could export this styles as GlobalStyle name without using styled-components so we don't have to change all import from all apps in the project?
why you dont create main.css and import it on your index.css or app.css , its download and cache on users browser so you don't need to use global styled component anymore
It seems like you're looking for something like injectGlobal:
import { injectGlobal } from 'styled-components';
injectGlobal`
/* your #font-face stuff here */
`
This seems like it would be a good fit for your situation, as it would be relatively easy to transition from the existing structure using createGlobalStyle to one that uses this.
In your case, the code would look like:
import { injectGlobal } from 'styled-components';
injectGlobal`
#font-face {
font-family: 'Name';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/name/v12/iJWZBXyIfDnIV5PNhY1KTN7Z-Yh-B4iFU0U1Z4Y.woff2) format('woff2');
}
// more fonts..
}
If you wish to use a solution that is backwards-compatible with any code that is rendering <GlobalStyle />, you can include a null component as the default export as a stop-gap solution, alongside your injectGlobal code:
export default () => null;
Would this solve your problem?
You can also bind the style directly inside the JS file
var stylingObject = {
div: {
color: "red",
border: "1px solid red"
}, input: {
margin: "2px",
padding: "5px"
}
}
function App() {
return (
<div style={stylingObject.div}>
<input style={stylingObject.input} type="text" />
</div>
);
}
Originally I had hoped to import some CSS file with the fonts defined there and then just importing it so it would affect the entire page, obviously because the way react works such a thing isn't possible cause it would take place only in the imported component not in the one that did the import.
the reason createGlobalStyle from styled-components renders each time is also due to react's workings - when we set the style for a "component like" (or actual component) object, like every react component its not static and renders only when needed. Even if we make it render by force on page load its not the same one (cause on each page we render it separately) so keeping up with the current config doesn't seem to be possible by react's standard.
If we want to make the styles static or "more" static we would have to :
either import them in each page separately - making us do a major refactor
or use either createGlobalStyle (allowing us to use our already created styled-components component) or importing a main css file in the main application component like in the example below:
globalStyles.js
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
background: teal;
font-family: Open-Sans, Helvetica, Sans-Serif;
}
`;
export default GlobalStyle;
App.js
import React, { Fragment } from 'react';
import GlobalStyle from './theme/globalStyle';
import Content from './components/Content';
function App() {
return (
<Fragment>
<GlobalStyle />
<Content />
</Fragment>
);
}
export default App;
If you have a rather large global stylesheet like we did while migrating, you can use styled-components css method to leverage styled-components (css) IDE syntax highlighting & linting you can also do the following:
import React from 'react'
import { createGlobalStyle, css } from 'styled-components'
const Reset = css`
* {
box-sizing: border-box;
}
`
const Accessibility = css`
.hidden {
display: none !important;
visibility: hidden;
}
`
const BaseStyles = createGlobalStyle`
${Reset};
${Accessibility};
`
export const GlobalStyles = () => (
<>
<BaseStyles />
</>
)
Import GlobalStyles and render as sibling to {children}

Using SCSS In Material UI React directly

I have some issue using scss directly in material ui, because not all styles are applied. Tried to use makeStyle, but because I use class component, it gives warning about invalid hook call.
The style :
.table-header {
background-color: #005CAA; //only this style works
color: white;
font-weight: bold;
text-align: center;
}
I call in in TableCell component from Material UI
<TableCell className="table-header">Invoice Number</TableCell>
For the scss file, I import it in parent component App.tsx, or I need to import the file directly in the Table component? Thx
I follow the makeStyles approach as it's recommended way of overriding the material-ui styles, else you'd have to use !important in your css/scss files to override the material-ui styles.
https://mui.com/styles/basics/
// component file
import React from 'react';
import { TextLineStyles } from './styles';
export default function TextLine({ text }) {
const classes = TextLineStyles()
return <div className={classes.root}>
<div data-title="line" >
<div data-title="text">
{text}
</div>
</div>
</div>
}
// style.js
import { makeStyles } from "#material-ui/core/styles";
export const TextLineStyles = makeStyles(theme => ({
root: {
'& [data-title="line"]': {
borderTop: `1px solid lightgray`,
'& [data-title="text"]': {
color: 'red' // scss like nesting
}
}
}
}));
If you want to use CSS/SCSS class in MUI component, you should import the file directly in the Table component. But, it's not good to use SCSS with MUI component, you should use makeStyles or withStyles to style the MUI component.
I am not sure if it is the best practice, in fact thats why I ended up in this post.
Here it explain how to use scss with material-ui: https://www.markmakesstuff.com/posts/mui-css-modules
"Just install node-sass"
"if you're working with an app you initialized with a script like create-react-app, you are in luck. No webpack edits necessary. Just give your module a name that ends with ".module.scss""
OTHERWISE
2') You need to "make some minor edits to your webpack config"
"You can then import your module with a name then use that to refer to your classes when writing your fancy JSX"

How can I setup SCSS files (ViewEncapsulated way) in 'react app 2' like Angular component specific SCSS?

I installed 'react app 2' as well as node-sass. It's working fine with SCSS. But I just want to know how can I create component specific SCSS like Angular (that will never be a conflict with other components SCSS)
Angular automatically add an attribute for ViewEncapsulation see below example
In angular, there is an option for
encapsulation: ViewEncapsulation.None (Use to disable CSS Encapsulation for this component)
enter link description here
I know the question is old, but it has no answer, thus I want to share this article. Alsomst does the trick, with the exception that it seems to does not have support for something like ::ng-deep
React doesn't have native component styles like Angular does because it aims to keep away from any functionality that could easily be handled by third-party packages. So you have two pretty simple options:
Use styled-components to create component-specific styles. This is a pretty straightforward package that allows you to define styles for each element within a component and you can even pass variables into the styles. It generates internal CSS (kept in <style> tags in the document head) which will take precedence over external styles by default. Example:
// MainComponent.jsx
import React from 'react';
import styled from 'styled-components';
const Title = styled.h1`
color: red
`
const MainComponent = (props) => <Title>Hello World</Title>
In each of your components, add a class or ID to the root element so that you can simply add that selector to the beginning of your SCSS to only style that specific component. Example:
// MainComponent.jsx
import React from 'react';
const MainComponent = (props) => (
<div className="main-component">
<h1>Hello World</h1>
</div>
)
// MainComponent.scss
.main-component {
h1 {
color: red;
}
}
Now only h1 elements in your MainComponent will be red.
//JS
import React from "react";
import "./yourComponentName.scss";
export default props => {
const { className, children, ...restOperator } = props;
return (
<a className={`yourComponentName ${className}` } {...restOperator}>
{children}
</a>
);
}
//yourComponentName.scss
.yourComponentName{
position:relative;
background:red;
/* your property and value use nesting*/
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}

styled-component generate custom css class

I have a question about the styled-components library. I know that this may not be an idiomatic way to do things, but I am curious if there is a styled-component method that can return a CSS class name. I would then be able to pass that class name into components that I render. This way, I can reuse some CSS. Then again, maybe this defeats the purpose of having isolated styled scoped to a single component.
For example, is there a function like generateCss?
const Button = styled.div`
background-color: blue;
`
const myCssClassName = styled.generateCss`
background-color: blue;
`
...
<Button className={myCssClassName} />
No, this is not possible. The whole idea of styled-components is to return new components. And if you want to create classes you should have a look at glamor or aphrodite. And here is a link to a discussion on github.
If you want to customize an existing styled component, you can use the .extend() API.
For example:
const Button = styled.div`
background-color: red;
`;
const BlueButton = Button.extend`
background-color: blue;
`;
export default () => (
<BlueButton />
);

Resources