Reputation: 27
My project is: when people click a <button>
or <li>
among a list of section, test, and practice etc. Each click will render a presentational component. My question is whether there is a solution to simplify my code as below.
createSection = () => {
this.setState({
sectionVisilibity: !this.state.sectionVisilibity
})
}
createPractice = () => {
this.setState({
practiceVisilibity: !this.state.practiceVisilibity
})
}
my initialstate is like this
sectionVisilibity:false,
practiceVisilibity:false,
And, the structure of state is
this.state={
.....,
sections:[
sec1:{name:'',description:''},
sec2:{...}
]
}
My button group is like this
const BtnGroup = ({ createSection, createPractice }) => (
<ul>
<li onClick={createSection}>Section</li>
<li onClick={createPractice}>Practice</li>
<li onClick={createSubSec}>Subsection</li>
<li onClick={createDownload}>Download</li>
<li onClick={createTest}>Test</li>
</ul>
)
Are there a way I can write like
createComponent=()=> {
//conditionally decide the click action by click event
//The thing I confused about is I did not pass any event here, but the click is work. It can change the flag between true and false.
}
Therefore, could anyone know how to grab value like multiple input I can use attribute to setState. How about onClick?
Thanks in advance!!
Upvotes: 0
Views: 67
Reputation: 4341
I have a simple solution for this kind of problem. the basic problem here is how to pass parameters to a onClick function.
what i do in this kind of scenario is to use data attributes.
handleClick(ev){
const type = ev.target.dataset.clickType;
// switch on type and you got the solution
}
const BtnGroup = ({ handleClick }) => (
<ul>
<li data-click-type="session" onClick={handleClick}>Section</li>
<li data-click-type="practice" onClick={handleClick}>Practice</li>
<li data-click-type="subsection" onClick={handleClick}>Subsection</li>
<li data-click-type="download" onClick={handleClick}>Download</li>
<li data-click-type="test" onClick={handleClick}>Test</li>
</ul>
)
if there is any click action that you want to map to the same handler . you just have to add the same data-click-type ="attribute"
in some cases you need to pass the entire object as an argument. that can also be achieved by using JSON.stringify`(ob)
also you are not creating any dynamic functions inside onClick
which makes it more efficient.
Upvotes: 1
Reputation: 1884
There is two another way to do that. First is make an object of array of your state and then in same order set your li tags in which buttons are present. And on click send index also so that on the basis of index you can change state. Second is same take your state in object array and on click send name also like the above answer. And in your function you can use seitch case or if else condition which button has beej clicked by the name.
this.state = {
data: [
{createSection:false},
{createBlock:false}
]
}
onClick(e,index,propertyName){
let data = this.state.data;
data[index].propertyName = true;
this.setState({data:data});
}
<li key={index}> <button onClick
{(e)=>this.onClick(e,index,'createSection')}> Create Section </button>
</li>
<li key={index}> <button onClick=
{(e)=>this.onClick(e,index,'CreateBlock')}> Create Section </button>
</li>
Keep that in mind that button order must be same as states.
Upvotes: 0
Reputation: 1398
You could in theory do some conditional logic on the event, but I don't think you want to do that.
Try something like:
<li onClick={() => createComponent('practice')}>Practice</li>
Upvotes: 1