Search code examples
javascriptreactjsstyled-components

How to change style of styled-component dynamically?


I am currently learning about using styled-components in React, and having trouble with implementing this.

I have a row of buttons (defined as divs). When a button is clicked, I want it's background to fill with a certain color. All of the other buttons should stay 'unselected'. Here is what I have so far:

import React from 'react';
import styles from 'styled-components';

const ButtonsRow = styles.div`
    display: flex;
    justify-content: space-evenly;
`;

const Button = styles.div`
    cursor: pointer;
    :hover {
        background-color: gray;
    }

    background-color: ${props => props.selected ? 'red' : 'none'};
`;

class ButtonsContainer extends React.Component {

    handleClick = (e) => {
      // add 'selected' prop to the clicked <Button>?
    }

    render() {
        return(
            <ButtonsRow>
                <Button onClick={this.handleClick}>People</Button>
                <Button onClick={this.handleClick}>Members</Button>
                <Button onClick={this.handleClick}>Games</Button>
            </ButtonsRow>  
        );
    }
}

export default ButtonsContainer;

If I button is clicked, I think I wanted to give it the 'selected' prop. That way, if it has the prop, then it will fill the background color. If it doesn't have it, then it doesn't have a background color. I thought that maybe I could use state to do this, but if I were to do that, I think it would apply to every button. Thanks for any help.


Solution

  • You need to manage every Button's state.

    All solutions will different in "how" you manage buttons state (as a single object/array/etc...), the main concept is to get the button's id in order to know which state you refer to.

    In the next simple example, I use a curried function to provide the button id.

    Another simple solution can be with passing the id attribute to your button and querying it on button click.

    const ButtonsRow = styled.div`
      display: flex;
      justify-content: space-evenly;
    `;
    
    const Button = styled.div`
      cursor: pointer;
      :hover {
        background-color: gray;
      }
    
      background-color: ${props => (props.selected ? 'red' : 'none')};
    `;
    
    class ButtonsContainer extends React.Component {
      state = {
        first: false,
        second: false,
        third: true
      };
    
      toggle = buttonName => () => {
        this.setState(prev => ({ [buttonName]: !prev[buttonName] }));
      };
    
      render() {
        const { first, second, third } = this.state;
        return (
          <ButtonsRow>
            <Button selected={first} onClick={this.toggle('first')}>
              People
            </Button>
            <Button selected={second} onClick={this.toggle('second')}>
              Members
            </Button>
            <Button selected={third} onClick={this.toggle('third')}>
              Games
            </Button>
          </ButtonsRow>
        );
      }
    }
    

    Edit Q-58628628-ButtonToggle