Passing in same prop to multiple styled components - reactjs

I have 3 React Components that are all being passed the same prop isNewListingsHeader. I am using Styled Components for CSS styling. I'm wondering if there is a cleaner way of passing this prop into the 3 different styled components SortBarWrapper, SortOptionsWrapper, and SortOptionsWrapper so that I don't have to define isNewListingsHeader each time.
// Styled Components
const SortBarWrapper = styled.div`
position: relative;
${props => !props.isNewListingsHeader && `
height: 100px;
`}
`
const SortLineWrapper = styled.div`
width: 100%;
${props => !props.isNewListingsHeader && `
position: absolute;
bottom: 0;
`}
`
const SortOptionsWrapper = styled.div`
box-sizing: border-box;
${props => !props.isNewListingsHeader && `
padding-bottom: 24px;
padding-top: 32px;
`}
`
render () {
return (
<SortBarWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
<SortLineWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
<SortOptionsWrapper isNewListingsHeader={this.props.isNewListingsHeader}>
// Display Sort Options
</SortOptionsWrapper>
</SortLineWrapper>
</SortBarWrapper>
)
}

What you are doing is not incorrect but I can understand you wanting to DRY up your code. I am not going to say what is the "right" way because there is technically no correct way, just ways you prefer to do it based on your stack (for example, are you using Redux or any other state management?).
This medium post covers several methods of deep nesting components.
Explore that and pick which works for you. But for the sake of this conversation - you are doing it correctly and in the "React way."

We can use context api. Create a provider and Consumer. Wrap all the components inside the provider, Provider accepts a value prop and the data in this prop is available to all the child consumers. And can use them inside consumer.
“Why you should consider the new Context API in React? — A deep dive” by Mahesh Haldar https://link.medium.com/zrYj36RnhU

Related

How to make Styled components generic to receive parameters?

I'm trying to use Styled Components with React FC. I want to display few details inside a div container, which all has the same stylings. Instead of writing hard coded such as Name: Height: Weight: etc. in the h-tags, can I do it in a more generic way to pass the text as parameter?
This is the way I have implemented, but I am thinking there should be some better way to do it. Like giving a parameter to the Styled component.
const CardContentContainer= styled.div`
margin: 4px;
padding: 4px;
text-align: left;
font-size: 14px;
`;
const CardContentDetails = styled.h3`
font-weight: normal;
color: #fff;
margin: 8px;
white-space: nowrap;
`;
this is the code inside the return:
return (
<CardContentContainer>
<CardContentDetails>
Name: {ItemDetails?.name}
</CardContentDetails>
<CardContentDetails>
Height:{ItemDetails?.height}
</CardContentDetails>
<CardContentDetails>
Weight:{ItemDetails?.weight}
</CardContentDetails>
</CardContentContainer>
);
You cant pass such props to Styled components because the main point of SC is to apply a custom style to that component. To make it receive some custom props, you have to wrap it inside another component like so...
const StyledTextField = styled(TextField)`
margin-bottom: 1rem;
width: 20em;
`;
const Comp: React.FC<{ title: string }> = ({ title }) => (
<StyledTextField>{title}</StyledTextField>
);
return (
<Comp title="some title" />

Question about mixing styled-components with material-ui

Hello I am a react newbie and new to styling as well :)
I am trying to style the material-ui Button component with styled components
I am doing this by overriding global class names, I know material-ui introduced global class names like MuiButton-root etc
I am not clear on the use of "&" in parent selector, for example:
const StyledButton = styled(Button)`
&.MuiButton-root {
width: 500px;
}
.MuiButton-label {
color: ${props => props.labelColor};
justify-content: center;
}
`;
The above code works and can achieve the following:
The Button has a width of 500px
The label has a color of red (labelColor is passed in as a prop)
Please see sandbox below for full code
Question:
Why do I need "&" selector for the MuiButton-root, whereas for the MuiButton-label I don't?
Also is this the best way to style material-ui with styled components?
Please see the following sandbox: https://codesandbox.io/embed/practical-field-sfxcu
The '&' selector is used to target the classes and neighbouring elements/classes. Take a look at cssinjs. Its the underlying system behind MUI's styling.
But in short to answer your question;
const StyledButton = styled(Button)`
&.MuiButton-root { //this targets any class that is added to the main component [1]
width: 500px;
}
.MuiButton-label { //in css-in-js this is effectively '& .MuiButton-label [2]
color: ${props => props.labelColor};
justify-content: center;
}
[1] Targets main classes on component
<StyledButton className='test bob'> << this element is targeted
</StyledButton>
[2] Targets child elements either through class or element type. Note the space between & and the actual class.
<StyledButton className='test bob'>
<span className='MuiButton-label'>test</span> << this element is targeted instead
</StyledButton>
You can also use the element tag directly
span {
color: ${props => props.labelColor};
justify-content: center;
}

Emotion.js how to do composition / conditional styling in react-native?

https://github.com/emotion-js/emotion/tree/master/packages/native
gives example
style={css`
border-radius: 10px;
`}
However, I can't figure out how I can do composition as done in https://emotion.sh/docs/composition with react-native
<div css={[danger, base]}>
Nor I can't do conditional styling as done in https://emotion.sh/docs/styled
const Button = styled.button`
color: ${props =>
props.primary ? 'hotpink' : 'turquoise'};
`
Even if I could do, they use two different methods one using css one using styled . How can I get the two at the same time with react-native?
Question 1: How to do composition in emotion/native in React Native?
It's really simple all you need to is use style property like so:
const style1 = css`
font-size: 40px;
`
const color = css`
color: red;
`
// And then in your component you can pass the all your style objects
// in an array to style property
<Text style={[fontSize, color]}>Hello world</Text>
Question 2: Conditional style in emotion/native in React Native?
const Description = styled.Text`
font-size: ${props => props.fontSize !== undefined ? props.fontSize : "40px"};
color: hotpink;
`
<Description fontSize={"60px"}>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Description>
Here's a working exampe as a snack

Styled components: nested className selectors vs multiple styled components

In general, are there any significant performance differences between using one of these approaches over the other?
When using styled components I've noticed two common approaches:
Have a styled parent component that uses className selectors to target child nodes for styling, and encapsulates those styles in the one place.
Have multiple styled components for each individual node that requires styling, independent of any parent styled components.
1 - nested selectors
const MyComponent = styled.div`
display: inline-block;
position: relative;
.MyChildComponent {
position: absolute;
background: red;
}
.MySubComponent {
background: yellow;
}
`
// In use
<MyComponent>
<span className="MyChildComponent>A goose!</span>
<button className="MySubComponent">Click bait</button>
</MyComponent>
2 - discrete components
const MyComponent = styled.div`
display: inline-block;
position: relative;
`
const MyChildComponent = styled.span`
position: absolute;
background: red;
`
const MySubComponent = styled.button`
background: yellow;
`
// In use
<MyComponent>
<MyChildComponent>A Goose!<MyChildComponent>
<MySubComponent>Click bait</MySubComponent>
<MyComponent>
Obviously there are situational reasons to mix and match these approaches, and I'm not taking into consideration use cases where a component may be re-used throughout a code base. I'm instead asking in the context of large chunks of markup that are unlikely to change or be shared.

Styled components for colored tags

Styled components looks great, but I am having trouble organizing my components. My first venture with is a tag list, that automatically colors the tags. After some trial I came up with a component that can be used like this:
// An array of tags. The string hashes determine the color
<ColorTags tags={post.frontmatter.tags} inline/>
It is implemented as follows:
components/
ColorTags // functional component
ColorTagLI // styled component
ColorTagUL // styled component
With:
// ColorTags
import ColorTagLI from './ColorTagLI'
import ColorTagUL from './ColorTagUL'
export default ({tags, inline}) =>
<ColorTagUL>
{tags.map( tag =>
<ColorTagLI key={tag} colorString={tag} inline>
<Link to="/">
{tag}
</Link>
</ColorTagLI>
)}
</ColorTagUL>
// ColorTagUL
export default styled.ul`
list-style-type: none;
margin: 0;
padding: 0;
`
// ColorTagLI
const colorHash = new ColorHash({lightness: [0.4, 0.5, 0.6]});
const hslColor = cString => {
const [h, s, l] = colorHash.hsl(cString)
return `hsl(${h}, ${s*100}%, ${l*100}%)`
}
export default styled.li`
color: white;
background-color: ${props => hslColor(props.colorString)};
display: ${props => props.inline ? 'inline-block' : 'block'};
padding: 0.25rem 0.5rem;
margin: 0.25rem;
> a { text-decoration: none; color: white; }
`
Some questions I have:
What's a good way to discern between styled and regular components? I
decided on appending the HTML tag to the styled components, since
they are always tied to that.
Is it not a problem to have the Link tag inside a Styled component?
Should the ColorTag components be in a folder of themselves? Because they are tightly coupled.
Is using theinline prop a smart way to switch between configurations? It may
result in a lot of conditional statements for margins, padding and
media queries... Perhaps better make two different components?
You can use utility function isStyledComponent.
Why would it be a problem to have a Link component inside styled component?
Matter of opinion, if you believe they are tightly coupled you can create /ColorTag directory with index.js file that exports only what should be exposed.
Yes it may result in a lot of conditional statements, that's why you can extend styles on styled components.
I hope I understood you right and my answers are clear.

Resources