Styled-components and react-icons <IconContext.Provider> component - javascript

i'm new to styled-components and i want to use <IconContext.Provider> from react icons this is my react component:
<myComp>
<AiFillPlusCircle />
</myComp>
and this is my styled components code:
import { IconContext } from 'react-icons';
export const myComp= styled(IconContext.Provider)`
color: rgb(71, 71, 71) !important;
vertical-align: middle !important;
font-size: 1.7rem !important;
`;
but it doesn't work!

When you wrap some component with styled hoc, it just passes className prop to your component.
IconContext.Provider expects only value prop. This prop is object and can contain style, attr or className values. You can just pass style attribute to configure it like this:
const MyProvider = ({children}) => <IconContext.Provider value={{ style: { someStyle: someValue } }}>{children}</IconContext.Provider>;
However, if you would like to use styled-components, it could be possible like this:
const MyProvider = ({className, children}) => <IconContext.Provider value={{className}}>{children}</IconContext.Provider>;
const MyProviderStyled = styled(MyProvider)`
some-style: some-value;
`;

Related

how to use hover in objects in react

I defined a object useStyle and called it in the component SecondTest defined background color, is it possible to add hover in the object useStyle
const useStyle = {
backgroundColor: "red",
};
function SecondTest() {
return <div style={useStyle}>SecondTest go down</div>;
}
export default SecondTest;
You can use Radium React Library
import React from "react";
import Radium from "radium";
const style = {
color: "#000000",
":hover": {
color: "#ffffff"
}
};
const MyComponent = () => {
return <section style={style}>hello world</section>;
};
const MyStyledComponent = Radium(MyComponent);
export default function App() {
return (
<>
<MyStyledComponent />
</>
);
}
You can accomplish it with events like onMouseEnter & onMouseLeave if you wish to use javascript to solve your issue. Easier way to do it would be just to give an element className like
<section className='myClass'>hello world</section>
and then just to add desired properties in your .css file which you can import in your component or globally.
.myClass {
color: #000000;
}
.myClass:hover {
color: #ffffff;
}
It is not possible to add hover with in-line styles.

How do I reference a styled-component that is a functional component?

This is the most basic example I could think of:
import React from 'react';
import {
css,
} from 'styled-components';
const Foo = (props) => {
console.log(props);
const {
children,
} = props;
return <div {...props}>{children}</div>;
};
export default () => {
return <div
css={css`
${Foo} {
background: #f00;
}
`}
>
<Foo>FOO</Foo>
</div>;
};
In this example, I want to style Foo component that is a descendent of div.
I would expect the resulting markup to look something like:
<div class="test__Foo-wusfqk-0 hNfawX">FOO</div>
However, instead it is simply:
<div>FOO</div>
It seems like no styling is applied anywhere.
Furthermore, the component Foo is rendered only once, but it is invoked twice, with different parameters:
{children: {…}, theme: {…}}
children: {$$typeof: Symbol(react.element), key: null, ref: null, props: {…}, type: ƒ, …}
theme: {}
{children: "FOO"}
I should mention that I tried:
// #flow
import React from 'react';
import styled, {
css,
} from 'styled-components';
const Foo = styled((props) => {
const {
className,
children,
} = props;
return <div className={className}>{children}</div>;
});
export default () => {
return <div
css={css`
${Foo} {
background: #f00;
}
`}
>
<Foo>FOO</Foo>
</div>;
};
However, when executing this code in next.js I am getting the following error:
The component Styled(Component) with the id of "sc-dlnjPT" has been created dynamically.
You may see this warning because you've called styled inside another component.
To resolve this only create new StyledComponents outside of any render method and function component.
The component Styled(Component) with the id of "sc-hKFyIo" has been created dynamically.
You may see this warning because you've called styled inside another component.
To resolve this only create new StyledComponents outside of any render method and function component.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
which does not make much sense given the subject code snippet.
The main issue is that <Foo /> is not a styled component its a functional component
I think you would need to do
const Foo = styled.div`
background: #f00;
`
Then you can change the style of Foo using css and the $ refrence
The reason your code does not work is the following
This behaviour is only supported within the context of Styled Components: attempting to mount B in the following example will fail because component Foo is an instance of React.Component not a Styled Component.
const Foo = () => <div> </div>
const B = styled.div`
${Foo} {
}
`
However, wrapping Foo in a styled() factory makes it eligible for interpolation -- just make sure the wrapped component passes along className.
const Foo = (props) => {
console.log(props);
const {
children,
} = props;
return <div className="Test-Class" {...props}>{children}</div>;
};
const StyledFoo = styled(Foo)``
const Main = styled.div`
${StyledFoo} {
background: #f00;
}
`
Code Sandbox
import { render } from "react-dom";
import React from "react";
import styled from "styled-components";
const Foo = (props) => {
const { className, children } = props;
return <div className={className}>{children}</div>;
};
const Bar = styled(Foo)``;
const Main = styled.div`
${Bar} {
background-color: #000;
color: #fff;
}
`;
const App = () => {
return (
<Main>
{" "}
<Bar>Hello </Bar>{" "}
</Main>
);
};
render(<App />, document.getElementById("root"));
https://codesandbox.io/s/styled-components-forked-5s201?file=/index.js

Do I need to pass className prop to extend a component's style?

I created a Card component that I want to modify by extending it.
But in order to do that, I need to pass a prop called className like the code bellow.
import React from 'react';
import { CardStyle } from './style';
import { CardInterface } from './interface';
const Card = (props: CardInterface) => {
const { children, className } = props;
return (
<CardStyle className={className}>
{children}
</CardStyle>
);
};
export default Card;
My question is, There's no other way where I don't need to pass the className prop to my component in order to extend it?
The piece of code where I try to extend the Card.
export const CardWithTabs = styled(Card)`
border-radius: 0px;
`;
I expect import { CardInterface } from './interface'; looks like this:
export interface CardInterface {
className: string;
}
So if const Card = (props: CardInterface), when you extend CardWithTabs = styled(Card), CardWithTabs will inherit CardInterface and also require className.
<CardWithTabs className="bleh" />
To have className not required you can make className optional in your interface with a ?:
export interface CardInterface {
className?: string;
}
Or, when extending Card, drop the className prop from being passed on:
// You will need to add an interface for CardComponent of course
const CardComponent = ({
children,
className,
...rest
}) => <Card {...rest}>{children}</Card>;
const CardWithTabs = styled(CardComponent)`
/* Your styles */
`;
This answer is base on assumptions from the code supplied.

Styled-component object can't observe mobx changes

I would like an HOC generated by styled-components to re-render when one of its properties get changed. I'm using MobX for change detection.
This doesn't respond to changes, I think I understand why. The question is if there is a simple workaround to make it work.
const DemoComponent = observer(styled.div`
background-color: ${props => props.myObject.myObservableIsTrue ? 'red' :
'green'};
`);
It's hard to tell by this little snippet, but one of my guesses would be you are not injecting any store, so currently, no store is being connected to your component.
here's a simple example of how I used styled-components with mobx if it helps:
EDITED:
I've updated the code example.
Do you know the Container / Presentational pattern?
This was the missing link.
In order to keep your renders as little as possible
you need to separate your stateful component from each other.
Spread them across a Container component (aka Dumb Components)
This way you separate state concerns and render only the component with the changed state.
UPDATED:
https://codesandbox.io/s/zxx6o2pq3l
Sorry!!! A bit of a hack job, but attempt to bring your entire code inside the #inject("store") class:
import React from "react";
import { observer, inject } from "mobx-react";
import styled, { css } from "styled-components";
#inject("store")
#observer
export default class OtherComponent extends React.Component {
render() {
const MyWrapper = (store) => {
const Wrapper = styled.div`
border: 1px solid black;
display: flex;
justify-content: space-between;
color: ${({ color }) => color};
border: 2px solid ${({ color }) => color || "black"};
padding: 10px;
margin-bottom: 10px;
`;
return (
<Wrapper {...store}>
styled-component
<button onClick={store.changeColor}>change color</button>
</Wrapper>
);
}
const { store } = this.props;
return (
<div>
{
MyWrapper(store)
}
</div>
);
}
}
Mobx is actually read like this: #inject("store") #observer export default class...
So it really an extension of an extended component; only wrapped variables will apply!

styled components: how to select child component?

// card.js
import styled from 'styled-components'
const Heading = styled.h1`
color: red;
`;
const Summary = styled.p`
text-align: center;
`;
const Card = ({className, heading, summary}) => (
<div className={className}>
<Heading>{heading}</Heading>
<Summary>{summary}</Summary>
</div>
);
export default Card;
// cardWithBlueHeading.js
import styled from 'styled-components';
import Card from './card.js';
const CardWithBlueHeading = styled(Card)`
// How can I select the Heading component and make it blue?
`;
export default CardWithBlueHeading;
I'm trying to change the styles of a child component. These styles will likely be a one off situation. I'm trying to avoid selecting the HTML element h1 and pseudo selectors.
You can pass props to styled components like below:
import styled from 'styled-components'
const Heading = styled.h1`
color: ${props => props.color};
`;
Pass the color as prop
<Heading color='blue'/>
You can give your Heading a className property and then select it with
const CardWithBlueHeading = styled(Card)`
> .[classNameYouGive] {
background: blue;
}
`;
This is the standard css way.

Categories

Resources