Reputation: 5308
I have a list of items, if an item is clicked it shall show its content. Do I need for each list item a boolean
in the state object or can I do it with add and remove classname
like in jquery
?
Code:
<ul>
<li> item <div className="hidden"> some extra text ... </div> </li>
<li> item <div className="hidden"> some extra text ... </div> </li>
<li> item <div className="hidden"> some extra text ... </div> </li>
<li> item <div className="hidden"> some extra text ... </div> </li>
</ul>
Upvotes: 1
Views: 5870
Reputation: 104369
Do I need for each list item a boolean in the state object?
Yes, you need to maintain a boolean
for each list item in state
variable, and on the basis of that state
value, render the content of list
items, Try this:
this.state = {showItems: []}
onClick(index){
console.log(index);
let showItems = this.state.showItems.slice();
showItems[index] = !showItems[index];
this.setState({showItems});
}
<ul>
<li onClick={this.onClick.bind(this,0)}> item {this.state.showItems[0] ? <div> some extra text ... </div> : null} </li>
<li onClick={this.onClick.bind(this,1)}> item {this.state.showItems[1] ? <div> some extra text ... </div> : null}</li>
<li onClick={this.onClick.bind(this,2)}> item{this.state.showItems[2] ? <div> some extra text ... </div> : null} </li>
<li onClick={this.onClick.bind(this,3)}> item {this.state.showItems[3] ? <div> some extra text ... </div> : null}</li>
</ul>
Check this working Snippet:
class App extends React.Component {
constructor(){
super();
this.state = {showItems:[]}
}
onClick(index){
let showItems = this.state.showItems.slice(0);
showItems[index] = !showItems[index];
this.setState({showItems});
}
render() {
return (
<div className="App">
<ul>
<li onClick={this.onClick.bind(this,0)}> item {this.state.showItems[0] ? <div> some extra text ... </div> : null} </li>
<li onClick={this.onClick.bind(this,1)}> item {this.state.showItems[1] ? <div> some extra text ... </div> : null}</li>
<li onClick={this.onClick.bind(this,2)}> item{this.state.showItems[2] ? <div> some extra text ... </div> : null} </li>
<li onClick={this.onClick.bind(this,3)}> item {this.state.showItems[3] ? <div> some extra text ... </div> : null}</li>
</ul>
<div style={{marginTop: 100}}>*click on item to open submenu</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('container'));
li{
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='container'/>
Check fiddle
for working example: https://jsfiddle.net/mayankshukla5031/18hheyx1/
Upvotes: 3
Reputation: 6322
I think you should use react-bootstrap. else you can use state and update it manually.
const accordionInstance = (
<Accordion>
<Panel header="Collapsible Group Item #1" eventKey="1">
test
</Panel>
<Panel header="Collapsible Group Item #2" eventKey="2">
test 1
</Panel>
<Panel header="Collapsible Group Item #3" eventKey="3">
test 2
</Panel>
</Accordion>
);
ReactDOM.render(accordionInstance, mountNode);
Document : https://react-bootstrap.github.io/components.html#panels-accordion
Upvotes: 2
Reputation: 7298
Here is a very simple to use library, which lets you define conditions on classnames. Library is also called classnames
For instance:
import classNames from 'classnames'
<li> item
<div className={ classNames({
'some-static-classname' : true,
'hidden' : this.state.hiddenItems.includes('itemX')
}) }
>
some extra text ...
</div>
</li>
So this library is only useful to reduce the boilerplate on your conditions. What you need is also keeping the data of hidden/shown items. You might keep this kind of state in react internal state. Then just put your conditions.
Here is another similar question and answer I answered. Hope it helps.
Upvotes: 1