I am trying to add a class and remove it it's available already. I am doing to for each element separately. but it always refers the last element. what is the correct way to do this?
is there any easy and elegant way to do this?
here is my component:
import React from "react";
import "./style.css";
export default class App extends React.Component {
divRef;
constructor(props){
super(props)
this.divRef = React.createRef();
}
toggleView = (e) => {
e.preventDefault();
if(this.divRef.current.classList.contains("active")){
this.divRef.current.classList.remove("active"); //always refer div 2!?
return;
}
this.divRef.current.classList.add("active");
}
render(){
return (
<div class="parent">
<div ref={this.divRef}>
1
<a href="#" onClick={(e) => this.toggleView(e)}>toggle</a>
</div>
<div ref={this.divRef}>2
<a href="#" onClick={(e) => this.toggleView(e)}>toggle</a>
</div>
</div>
);
}
}
I would utilize state
to achieve this. No need for refs
.
import React from "react";
import "./style.css";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
view1: false,
view2: false
};
}
toggleView = (e, view) => {
e.preventDefault();
this.setState({ [view]: !this.state[view] });
};
render() {
return (
<div class="parent">
<div className={this.state.view1 ? "active" : ""}>
1
<a href="#" onClick={e => this.toggleView(e, "view1")}>
toggle
</a>
</div>
<div className={this.state.view2 ? "active" : ""}>
2
<a href="#" onClick={e => this.toggleView(e, "view2")}>
toggle
</a>
</div>
</div>
);
}
}
EDIT: Here I show how this approach scales when we have lots of items
import React from "react";
import "./style.css";
const NUM_ITEMS = 20;
const items = Array.from({ length: NUM_ITEMS }).map((_, idx) => ({
title: "title" + idx,
active: false
}));
const Item = ({ active, title, onToggle }) => (
<div className={active ? "active" : ""}>
{title}
<a
href="#"
onClick={e => {
e.preventDefault();
onToggle();
}}
>
toggle
</a>
</div>
);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items
};
}
toggleView = idx => {
const items = [...this.state.items];
items[idx] = { ...items[idx], active: !items[idx].active };
this.setState({ items });
};
render() {
return (
<div class="parent">
{this.state.items.map((item, idx) => (
<Item
key={item.title}
active={item.active}
title={item.title}
onToggle={() => this.toggleView(idx)}
/>
))}
</div>
);
}
}