Advanced Usage of Styled Components for your React App - Part 1
Tags: webdev, react, javascript, beginners
Published: 2021-02-15 12:12:29

In my previous post about [styled components](https://dev.to/olenadrugalya/intro-to-styled-components-for-your-react-app-2p6l) I wrote about the general features of **Styled Components**, how to set up and use them and why to use them in your React application.

This post will cover and show some advanced usage of Styled Components, so you will have more wide understanding of their flexibility and probably could learn and use some techniques.  

As we know already, **styled-components** is a library, which helps you to create components already with a style. It removes the mapping between components and styles. This means that when you're defining your styles, you're actually creating a normal React component, that has your styles attached to it.

So, let's get to practice and learn new features on the way. We are going to create a hamburger menu, which we can use for responsive application for mobile.

Our menu will be a separate styled component, which in its turn will be created from smaller styled components. Menu will consist of a *MenuButton* and *MenuNavigation* components.
We create a file called "Menu.js" and add the following code to it:

```react
export const Menu = () => {
  return (
    <>
      <MenuButton>
        <Line></Line>
        <Line></Line>
        <Line></Line>
      </MenuButton>
      <MenuNavigation>
        <NavList>
          <NavItem>
            <NavLink href="/">Home</NavLink>
         </NavItem>
         <NavItem>
            <NavLink href="/">About</NavLink>
         </NavItem>
       </NavList>
     </MenuNavigation>
    </>
  );
}
```
Next step is styling. We create a file called "Menu.styles.js" and add there the following code:

```react
import styled from "styled-components";

export const MenuButton = styled.div`
  cursor: pointer;
  width: 3rem;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
`;

export const Line = styled.div`
  width: 80%;
  height: 3px;
  background-color: white;
  margin: 0.2rem;
`;

export const MenuNavigation = styled.div`
  position: fixed;
  width: 200px;
  max-width: 70%;
  height: 100%;
  left: 0;
  margin-top: 1.4rem;
  z-index: 200;
  background-color: white;
  padding: 1rem 2rem;
  transition: all 0.7s ease;
  box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
`;

export const NavList = styled.ul`
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  align-items: center;
`;

export const NavItem = styled.li`
  margin: 5px 0;
  box-sizing: border-box;
  width: 100%;
  display: block;
`;

export const NavLink = styled.a`
  color: #8f5c2c;
  text-decoration: none;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0.5rem;
`;
```

Afterwards we need to import all created styled components to out Menu.js file so we can use them:

```react
import {
  MenuButton,
  Line,
  MenuNavigation,
  NavList,
  NavItem,
  NavLink
} from "./Menu.styles";
```

So, these are some general styles we have added to every component in out application. 
For now our navigation links look exactly the same, but what if we want About link to be different?

## Changing style based on Props

Since our styled NavLink is a component, it accepts `props` under the hood.  We can pass a function ("interpolations") to a styled component's template literal to adapt it based on received props.  
We pass attribute to NavLink component (lets call it `green`) and we can now use it in NavLink through `props`:

// Menu.js
```react
<NavLink green href="/">About</NavLink>
```
// Menu.styles.js
```react
export const NavLink = styled.a`
  color: #8f5c2c;
  text-decoration: none;
  width: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0.5rem;

${props => props.green &&`
    background: green;
    color: white;
  `}`
```
Now it is styled differently. And this is amazing! :) But this is not all what we can do with `props`.

## Changing Style of Specific Property based on Props

What if we want to change a style of just one single property for a specific component? We can do that also with using `props`.

For now both Menu button and navigation links are showing on our page, but this is not what we want exactly. We want to see navigation links ONLY when we click a button. How we can do that?

We can change `display` property of a MenuNavigation by passing needed behaviour (in our case, a string) through `display` attribute:

// Menu.js
```react
<MenuNavigation display={"none"} />
```

//Menu.styles.js
```react
export const MenuNavigation = styled.div`
  position: fixed;
  width: 200px;
  max-width: 70%;
  height: 100%;
  left: 0;
  margin-top: 1.4rem;
  z-index: 200;
  background-color: white;
  padding: 1rem 2rem;
  transition: all 0.7s ease;
  box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
  display:${props => props.display}
`;
```

Now we don't see navigation links anymore. But this is also not the behaviour we wanted. We want to change `display` dynamically: when we click MenuButton, we want to see navigation links, when we click button again, we want them to collapse again.  Let's implement that!

 ## Changing Style of Specific Property based on Props Dynamically

To implement the above behaviour, we need to pass either *true* or *false* to the `display` attribute and based on that the `display` property will be changed either to `block` or `none`.
To do that, first we need to create a `state`:
 
//Menu.js
```react
import { useState } from "react";
const [display, setDisplay] = useState(false);
```

We initialise `display` variable  as *false*, so if we use it now to set up *display*, we wont see anything but the button. When we click MenuButton, we change `display` variable  to 'true' and we should see navigation links.

Let's see the code: 

//Menu.js
```react
import { useState } from "react";
import {MenuButton, Line, MenuNavigation, NavList, NavItem, NavLink} from "./Menu.styles";


export const Menu = () => {

const [display, setDisplay] = useState(false);

 // This method will change display to opposite every time we call it
const handleClick = () =>{
  setDisplay(!display);
}

  return (
    <>
      <MenuButton onClick={handleClick}>
        <Line></Line>
        <Line></Line>
        <Line></Line>
      </MenuButton>
      <MenuNavigation display={display}>
        <NavList>
          <NavItem>
            <NavLink href="/">Home</NavLink>
         </NavItem>
         <NavItem>
            <NavLink green href="/">About</NavLink>
         </NavItem>
       </NavList>
     </MenuNavigation>
    </>
  );
}

```

//Menu.styles.js
```react
export const MenuNavigation = styled.div`
  position: fixed;
  width: 200px;
  max-width: 70%;
  height: 100%;
  left: 0;
  margin-top: 1.4rem;
  z-index: 200;
  background-color: white;
  padding: 1rem 2rem;
  transition: all 0.7s ease;
  box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
  display:${props => props.display}
`;
```

So here we receive `display` attribute through `props` to our component and we need to change `display` property somehow based on if we get `true` or `false`. How we can do it?

## Ternary Operator with Styled Components

We can use Ternary Operator to change the style of property conditionally. 
In our example, we will write the logic for `display` property like this:

//Menu.styles.js
```react
export const MenuNavigation = styled.div`
  position: fixed;
  width: 200px;
  max-width: 70%;
  height: 100%;
  left: 0;
  margin-top: 1.4rem;
  z-index: 200;
  background-color: white;
  padding: 1rem 2rem;
  transition: all 0.7s ease;
  box-shadow: 0px 8px 30px rgba(0, 0, 0, 0.2);
  display:${props => props.display ? "block" : "none"}
`;
```
Now it's all set up with button and navigation as we wanted. But we still have adjustments we would like to make. For example, set some media-queries, so we can only see hamburger menu on a small screen. Or we would like to add some styles for `hover` and `active` pseudo-classes for links or button right? or may be we want to add a `className` attribute to our component and use it instead? We can do all of these.....but in my next blog post!

So stay tuned and may be you would like Styled Components as much as i do :)

P.S. You can find the link to the project [HERE](https://codesandbox.io/s/advancedstyledcomponents-l5s0y) if you need it.

Thank you for reading my blog. Feel free to connect on [LinkedIn](https://www.linkedin.com/in/olenadrugalya/) or [Twitter](https://twitter.com/OlenaDrugalya) :)

<a href='https://ko-fi.com/J3J42JOOA' target='_blank'><img height='12' width=30% style='border:0px;height:12px;' src='https://cdn.ko-fi.com/cdn/kofi1.png?v=2' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>