Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
46
rated 0 times [  50] [ 4]  / answers: 1 / hits: 181696  / 8 Years ago, fri, february 5, 2016, 12:00:00

I have a state like this where I am setting active and class flag like this:



constructor(props) {
super(props);
this.state = {'active': false, 'class': 'album'};
}

handleClick(id) {
if(this.state.active){
this.setState({'active': false,'class': 'album'})
}else{
this.setState({'active': true,'class': 'active'})
}
}


And I have a list of items with class name from state:



<div className={this.state.class} key={data.id} onClick={this.handleClick.bind(this.data.id}>
<p>{data.name}</p>
</div>


Here how can I change the class name of particular div?


More From » reactjs

 Answers
22

Below is a fully functional example of what I believe you're trying to do (with a functional snippet).


Explanation


Based on your question, you seem to be modifying 1 property in state for all of your elements. That's why when you click on one, all of them are being changed.


In particular, notice that the state tracks an index of which element is active. When MyClickable is clicked, it tells the Container its index, Container updates the state, and subsequently the isActive property of the appropriate MyClickables.


Example




class Container extends React.Component {
state = {
activeIndex: null
}

handleClick = (index) => this.setState({ activeIndex: index })

render() {
return <div>
<MyClickable name=a index={0} isActive={ this.state.activeIndex===0 } onClick={ this.handleClick } />
<MyClickable name=b index={1} isActive={ this.state.activeIndex===1 } onClick={ this.handleClick }/>
<MyClickable name=c index={2} isActive={ this.state.activeIndex===2 } onClick={ this.handleClick }/>
</div>
}
}

class MyClickable extends React.Component {
handleClick = () => this.props.onClick(this.props.index)

render() {
return <button
type='button'
className={
this.props.isActive ? 'active' : 'album'
}
onClick={ this.handleClick }
>
<span>{ this.props.name }</span>
</button>
}
}

ReactDOM.render(<Container />, document.getElementById('app'))

button {
display: block;
margin-bottom: 1em;
}

.album>span:after {
content: ' (an album)';
}

.active {
font-weight: bold;
}

.active>span:after {
content: ' ACTIVE';
}

<script crossorigin src=https://unpkg.com/react@17/umd/react.development.js></script>
<script crossorigin src=https://unpkg.com/react-dom@17/umd/react-dom.development.js></script>
<div id=app></div>




Update: "Loops"


In response to a comment about a "loop" version, I believe the question is about rendering an array of MyClickable elements. We won't use a loop, but map, which is typical in React + JSX. The following should give you the same result as above, but it works with an array of elements.


// New render method for `Container`
render() {
const clickables = [
{ name: "a" },
{ name: "b" },
{ name: "c" },
]

return <div>
{ clickables.map(function(clickable, i) {
return <MyClickable key={ clickable.name }
name={ clickable.name }
index={ i }
isActive={ this.state.activeIndex === i }
onClick={ this.handleClick }
/>
} )
}
</div>
}

[#63434] Wednesday, February 3, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
hasancolec

Total Points: 603
Total Questions: 95
Total Answers: 98

Location: South Korea
Member since Sat, Oct 2, 2021
3 Years ago
;