Reputation: 710
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.
Upvotes: 7
Views: 18894
Reputation: 53874
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>
);
}
}
Upvotes: 7
Reputation: 6015
You have to create a variable to store the state of each button. A simpler approach may be to dynamically generate the buttons from an array and use the same to maintain the state.
class ButtonsContainer extends React.Component {
state = {
buttons = [{label:"People"},{label:"Members"},{label:"Games"}]
}
handleClick = (button) => (e) => {
this.setState((prevState) => ({
buttons: prevState.buttons.filter(btn => btn.label !== button.label)
.concat({...button,selected:!button.selected})
})
}
render() {
return(
<ButtonsRow>
{this.state.buttons.map(button => (<Button key={button.label} selected={button.selected} onClick={this.handleClick(button)}>{button.label}</Button>))}
</ButtonsRow>
);
}
}
export default ButtonsContainer;
Upvotes: 1