React styled-components: refer to other components

16.6k views Asked by At

According to styled-components doc's I can refer to another component to trigger, for example, a hover effect.

const Link = styled.a`
    display: flex;
    align-items: center;
    padding: 5px 10px;
    background: papayawhip;
    color: palevioletred;
`;

const Link2 = styled.a`
    display: flex;
    align-items: center;
    padding: 5px 10px;
    background: steelblue;
    color: white;

    ${Link}:hover & {
        background-color: greenyellow;
        color: black;
    }
`;

class Hello extends React.Component{
  render() {
    return(
      <div>
        <Link>Hello World</Link>
        <Link2>Hello Again</Link2>
      </div>
    )
  }
}

Basically, hovering mouse on my <Link> should trigger a change in background-color in <Link2>.

This is not happening. Any ideas why?

I prepared a code snippet here: https://codesandbox.io/s/qv34lox494

3

There are 3 answers

0
Adrien Lacroix On BEST ANSWER

You can refer to styled-components which are children of your styled-component, not side-by-side.

See a quote from the doc:

Here, our Icon component defines its response to its parent Link being hovered

For your problem, you can create a wrapper for both of your links, and use the adjacent sibling selector in CSS like this:

const Wrapper = styled.div`
    & ${Link}:hover + ${Link2} {
        background-color: greenyellow;
        color: black;
    }
`;

https://codesandbox.io/s/mo7kny3lmx

0
Grigory On

The other way is to modify your selector on Link2 to use siblings (now it's nested item selector). In that case you can get rid of extra wrapper

    const Link = styled.a`
    display: flex;
    align-items: center;
    padding: 5px 10px;
    background: papayawhip;
    color: palevioletred;
`;

const Link2 = styled.a`
    display: flex;
    align-items: center;
    padding: 5px 10px;
    background: steelblue;
    color: white;

    ${Link}:hover + & {
        background-color: greenyellow;
        color: black;
    }
`;

class Hello extends React.Component{
  render() {
    return(
      <div>
        <Link>Hello World</Link>
        <Link2>Hello Again</Link2>
      </div>
    )
  }
}
0
Anis On

you can do it like this. it works for many components:

const Hi0 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;
const Hi1 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;
const Hi2 = styled.div`
width:75px;
height:75px;
display: flex;
align-items: center;
padding: 5px 10px;
background: papayawhip;
color: palevioletred;
border-radius:50%;
`;

const Ind = styled.div`
width:75px;
height:75px;
border-radius:50%;
display: flex;
align-items: center;
padding: 5px 10px;
background: steelblue;
color: white;
transition:0.5s;

`;

 const Wrapper = styled.div`
 ${Hi0}:hover  ~ ${Ind} {
 background: blue;

 };
 ${Hi1}:hover  ~ ${Ind} {

 background: red;
 };
 ${Hi2}:hover  ~ ${Ind} {

 background: yellow;
 };


`;
class App extends React.Component{
render() {
 return(
        <Wrapper>
    <Hi0>Hello World</Hi0>
    <Hi1>Hello World</Hi1>
    <Hi2>Hello World</Hi2>
    <Ind>Hello Again</Ind>
        </Wrapper>
 )
}
}

 export default App;

sandboxexemple